【USACO Dec09】电视游戏问题

版权声明:转载请注明出处。 https://blog.csdn.net/TungstenC/article/details/83053933

题目描述

v ( 1 v 100 , 000 ) v(1\le v\le 100,000) 元钱和 n ( 1 n 50 ) n(1\le n\le 50) 种游戏平台,购买每种游戏平台的价格是 p i ( 1 p i 1 , 000 ) p_i(1\le p_i\le 1,000) ,第 i i 种游戏平台支持 g i ( 1 g i 10 ) g_i(1\le g_i\le 10) 种游戏,每种游戏的价格和对答案的贡献分别是 g p j ( 1 g p j 100 ) gp_j(1\le gp_j\le 100) p v j ( 1 p v j 1 , 000 , 000 ) pv_j(1\le pv_j\le 1,000,000) ,只有购买了游戏平台才能购买相应平台下的游戏,求用这 v v 元钱产生答案的最大值。

算法分析

定义 f [ i ] [ j ] f[i][j] 表示前 i i 种游戏平台花费 j j 元不购买第 i i 种游戏平台时的最大答案, d [ i ] [ j ] d[i][j] 表示前 i i 种游戏平台花费 j j 元购买第 i i 种游戏平台时的最大答案,设计状态转移方程。
可以使用滚动数组优化,时间复杂度大概是 O ( n v ) 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;
}

猜你喜欢

转载自blog.csdn.net/TungstenC/article/details/83053933
今日推荐