1. 程式人生 > >[USACO]又買飼料 單調隊列dp

[USACO]又買飼料 單調隊列dp

while str span iostream sam -i 商家 () i++

題目描述

約翰開車回家,又準備順路買點飼料了(咦?為啥要說“又”字?)回家的路程一共有 E 公裏, 這一路上會經過 N 家商店,第 i 家店裏有 F i 噸飼料,售價為每噸 C i 元。約翰打算買 K 噸飼料,他 知道商家的庫存是足夠的,至少所有店的庫存總和不會少於 K。除了購買飼料要錢,運送飼料也是 要花油錢的,約翰的卡車上如果裝著 X 噸飼料,那麽他行駛一公裏會花掉 X2 元,行駛 D 公裏需要 DX2 元。已知第 i 家店距約翰所在的起點有 X i 公裏,那麽約翰在哪些商店買飼料運回家,才能做到 最省錢呢?

輸入

? 第一行:三個整數 K,E 和 N,1 ≤ K ≤ 10000,1 ≤ E ≤ 500,1 ≤ N ≤ 500 ? 第二行到第 N + 1 行:第 i + 1 行有三個整數 X i ,F i 和 C i ,0 < X i < E,1 ≤ F i ≤ 10000,1 ≤ C i ≤ 10 7

輸出

? 單個整數:表示購買及運送飼料的最小費用

樣例輸入

2 5 3 3 1 2 4 1 2 1 1 1

樣例輸出

9

提示

在離家較近的兩家商店裏各購買一噸飼料,

則花在路上的錢是 1 + 4 = 5,花在店裏的錢是

2 + 2 = 4
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=505,M=10005;
typedef long long ll;
struct node
{
  ll x,w,v;
}a[N];
ll f[M],q[M],id[M];
bool comp(const node &p,const node &q){return p.x<q.x;} int main() { int n,m,e; scanf("%d%d%d",&m,&e,&n); for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&a[i].x,&a[i].w,&a[i].v); sort(a+1,a+n+1,comp); for(int i=1;i<=n;i++)a[i].x=e-a[i].x; for(int i=1;i<=m;i++)f[i]=2e16; f[
0]=0; ll tmp;int l,r; for(int i=1;i<=n;i++) { l=r=1;q[l]=0;id[l]=0; for(int j=1;j<=m;j++) { while(l<r && j-id[l]>a[i].w)l++; tmp=f[j]; f[j]=min(f[j],q[l]+j*j*a[i].x+j*a[i].v); while(l<=r && tmp-j*j*a[i].x-j*a[i].v<=q[r])r--; q[++r]=tmp-j*j*a[i].x-j*a[i].v;id[r]=j; } } printf("%lld\n",f[m]); return 0; }

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N=505,M=10005;
 8 const ll xy=2e15;
 9 struct node
10 {
11   int w,v,x;
12 }a[N];
13 ll F[N][M];
14 bool comp(const node &p,const node &q){return p.x<q.x;}
15 int main()
16 {
17   freopen("pp.in","r",stdin);
18   int n,m,e;
19   scanf("%d%d%d",&m,&e,&n);
20   for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].w,&a[i].v);
21   a[++n].x=e;
22   sort(a+1,a+n+1,comp);
23   for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)F[i][j]=xy;
24   F[0][0]=0;
25   ll now;int tmp;
26   for(int i=1;i<=n;i++)
27     {
28       for(int j=0;j<=m;j++)
29     {
30       tmp=j-a[i].w>=0?j-a[i].w:0;
31       if(F[i-1][tmp]==xy)break;
32       for(int k=tmp;k<=j;k++)
33         {
34           now=F[i-1][k]+k*k*(a[i].x-a[i-1].x)+a[i].v*(j-k);
35           if(now<F[i][j])F[i][j]=now;
36         }
37         }
38     }
39   printf("%lld\n",F[n][m]);
40 }

[USACO]又買飼料 單調隊列dp