题解:P2967 [USACO09DEC] Video Game Troubles G

很好的一道题,使我的背包旋转,

Solution P2967

Idea

如果我们直接背包,第一不方便考虑限制,第二可能会 TLE。

但是不难发现每一个游戏机之间是不冲突的。这意味着第 ii 个游戏机如何选取不会影响第 i+1i+1 个游戏机的选取。

我们考虑每个游戏机当做一个子任务。然后对这个子任务跑 01 背包。

dpi,jdp_{i,j} 为考虑到游戏机 ii 的总花费为 jj 的最大价值。

对于选了的情况,显然有先选这个游戏机的价格:dpi,j=dpi1,jvdp_{i,j}=dp_{i-1,j-v},其中 vv 为游戏机价格。

然后选游戏,做 01 背包即可,dpi,j=max(dpi,jv+w,dpi,jdp_{i,j}=\max(dp_{i,j-v}+w,dp_{i,j},其中 vv 为游戏价格,ww 为价值。、

可能有人会问为什么是 dpi,jvdp_{i,j-v}。实际上因为限制,我们要求转移必须以选了这个游戏机作为前提。如果先转移选了,这个时候 dpi,jvdp_{i,j-v} 一定是一个选了的状态。

如果这个游戏机不选,就很简单:dpi,j=dpi1,jdp_{i,j}=dp_{i-1,j}

Code

#include<bits/stdc++.h>
using namespace std;
const int N=55,M=100005;
int n,m,w,v,d,dp[2][M],k;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&d,&k);
		for(int j=d;j<=m;j++){
			dp[i&1][j]=dp[(i-1)&1][j-d];
		}
		while(k--){
			scanf("%d%d",&v,&w);
			for(int j=m;j>=v+d;j--){//v+d 的原因是要包括游戏机的价格
				dp[1&i][j]=max(dp[i&1][j],dp[i&1][j-v]+w);
			}
		}
		for(int j=0;j<=m;j++){
			dp[i&1][j]=max(dp[i&1][j],dp[(i-1)&1][j]);
		}
	}
	printf("%d",dp[n&1][m]);
	return 0;
}
posted @   Weslie_qwq  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示