1. 程式人生 > >【USACO Dec09】電視遊戲問題

【USACO Dec09】電視遊戲問題

題目描述

v(1v100,000)v(1\le v\le 100,000) 元錢和 n(1n50)n(1\le n\le 50) 種遊戲平臺,購買每種遊戲平臺的價格是 pi(1pi1,000)p_i(1\le p_i\le 1,000),第 ii 種遊戲平臺支援 gi(1gi10)g_i(1\le g_i\le 10) 種遊戲,每種遊戲的價格和對答案的貢獻分別是 gpj(1gpj100)gp_j(1\le gp_j\le 100)pvj(1pvj1,000,000)pv_j(1\le pv_j\le 1,000,000)

,只有購買了遊戲平臺才能購買相應平臺下的遊戲,求用這 vv 元錢產生答案的最大值。

演算法分析

定義 f[i][j]f[i][j] 表示前 ii 種遊戲平臺花費 jj 元不購買第 ii 種遊戲平臺時的最大答案,d[i][j]d[i][j] 表示前 ii 種遊戲平臺花費 jj 元購買第 ii 種遊戲平臺時的最大答案,設計狀態轉移方程。 可以使用滾動陣列優化,時間複雜度大概是 O(nv)O(nv),有十倍的常數。

程式碼實現

#include <cstdio>
#include <cstring>
#include <algorithm> const int maxn=55; const int maxv=(int)1e5+5; int f[2][maxv],d[2][maxv]; int main() { int n,v;scanf("%d%d",&n,&v); memset(f,0x80,sizeof(f));f[0][0]=0; memset(d,0x80,sizeof(d));d[0][0]=0; for(int i=1;i<=n;++i) { int p,g;scanf("%d%d",&p,&g); for(int j=0;j<=
v;++j) { f[i&1][j]=std::max(f[(i-1)&1][j],d[(i-1)&1][j]); if(j>=p) d[i&1][j]=std::max(f[(i-1)&1][j-p],d[(i-1)&1][j-p]); } for(int j=1;j<=g;++j) { int gp,pv;scanf("%d%d",&gp,&pv); for(int k=v;k-gp>=p;--k) d[i&1][k]=std::max(d[i&1][k],d[i&1][k-gp]+pv); } } int ans=0; for(int i=0;i<=v;++i) ans=std::max(ans,std::max(f[n&1][i],d[n&1][i])); printf("%d\n",ans); return 0; }