【USACO Dec09】电视游戏问题

本文介绍了一种基于动态规划的游戏购买策略优化算法,旨在利用有限的资金最大化游戏收益。通过定义状态和设计状态转移方程,算法能在O(nv)的时间复杂度内解决问题,其中n为游戏平台数量,v为资金总额。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

v(1≤v≤100,000)v(1\le v\le 100,000)v(1v100,000) 元钱和 n(1≤n≤50)n(1\le n\le 50)n(1n50) 种游戏平台,购买每种游戏平台的价格是 pi(1≤pi≤1,000)p_i(1\le p_i\le 1,000)pi(1pi1,000),第 iii 种游戏平台支持 gi(1≤gi≤10)g_i(1\le g_i\le 10)gi(1gi10) 种游戏,每种游戏的价格和对答案的贡献分别是 gpj(1≤gpj≤100)gp_j(1\le gp_j\le 100)gpj(1gpj100)pvj(1≤pvj≤1,000,000)pv_j(1\le pv_j\le 1,000,000)pvj(1pvj1,000,000),只有购买了游戏平台才能购买相应平台下的游戏,求用这 vvv 元钱产生答案的最大值。

算法分析

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值