[USACO]又買飼料 單調隊列dp
阿新 • • 發佈:2017-06-30
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