1. 程式人生 > 實用技巧 >【Usaco 2009 Gold 】JZOJ2020年9月19日提高B組T2 電視遊戲問題

【Usaco 2009 Gold 】JZOJ2020年9月19日提高B組T2 電視遊戲問題

【Usaco 2009 Gold 】JZOJ2020年9月19日提高B組T2 電視遊戲問題

題目

Description

農夫約翰的奶牛們遊戲成癮!本來FJ是想要按照陶叫獸的做法拿她們去電擊戒癮的,可是後來他發現奶牛們玩遊戲之後比原先產更多的奶。很明顯,這是因為滿足的牛會產更多的奶。
但是,奶牛們在哪個才是最好的遊戲平臺這個問題上產生了巨大的分歧。一隻奶牛想要買一臺Xbox 360來跑《光暈3》;另外一隻奶牛想要一臺任天堂Wii來跑《任天堂明星大亂鬥X》;第三隻奶牛想要在PlayStation 3上面玩《潛龍諜影4》,順便還能看某些高畫質的日本電影。
FJ想要在給定的預算內購入一些遊戲平臺和一些遊戲,使他的奶牛們生產最多的奶牛以養育最多的孩子。
FJ研究了N(1 <= N <= 50)種遊戲平臺,每一種遊戲平臺的價格是P_i(1 <= P_i <= 1000),並且每一種遊戲平臺有G_i(1 <= G_i <= 10)個只能在這種平臺上執行的遊戲。很明顯,奶牛必須先買進一種遊戲平臺,才能買進在這種遊戲平臺上執行的遊戲。每一個遊戲有一個遊戲的價格GP_j(1 <= GP_j 價格 <= 100)並且有一個產出值PV_j(1 <= PV_j<= 1000000),表示一隻牛在玩這個遊戲之後會產出多少牛奶。
最後,農夫約翰的預算為V(1 <= V <= 100000),即他最多可以花費的金錢。請幫助他確定應該買什麼遊戲平臺和遊戲,使得他能夠獲得的產出值的和最大。
考慮下面的資料,有N種遊戲平臺,並且有V=800 預算
第一種遊戲平臺花費$300並且有兩個遊戲,價格分別為30和25,它們的產出值如下所示:

遊戲 #花費 產出值
1 30 50
2 25 80

第二種平臺價格為 $600,並且只有一種遊戲:

遊戲 #花費 產出值
1 50 130

第三種平臺價格為$400,並且有三種遊戲:

遊戲 #花費 產出值
1 40 70
2 30 40
3 35 60
農夫約翰應該買第1和第3種平臺,並且買平臺1的遊戲2,還有平臺3的遊戲1和遊戲3。使得最後他最後的產出值最大,為210
預算: 800
平臺 1 -300
遊戲 2 -25 80
平臺 3 -400
遊戲 1 -40 70
遊戲 3 -35 60
-------------------------------------------
總計: 0 (>= 0) 210

Input

第1行: 兩個由空格隔開的整數: N和V
第2到第N+1行: 第i+1行表示第i種遊戲平臺的價格和可以在這種遊戲平臺上面執行的遊戲。包含: P_i, G_i還有G_i對由空格隔開的整數GP_j, PV_j

Output

第1行: 農夫約翰在預算內可以得到的最大的產出值。

Sample Input

3 800
300 2 30 50 25 80
600 1 50 130
400 3 40 70 30 40 35 60

Sample Output

210

題解

題意

\(n\)個平臺,每個平臺內有一些遊戲
每個平臺需要一定價格,每個遊戲也需要一定價格,也給予一定價值
問在不超過預算的前提下的最大價值

分析

易想到DP
\(f[i][j]\)表示第\(i\)個平臺花了\(j\)元的最大價值

變數:
\(p\)表示當前平臺價格
\(v\)表示預算
\(x\)表示遊戲價格
\(y\)表示遊戲價值

對於當前平臺\(i\)
可以選擇買平臺而不買遊戲
\(f[i][j]=f[i-1][j-p]\)

\(j\)\(p\)~\(v\)
然後對於當前平臺做一次01揹包
最後可能沒有不買這個平臺優
\(f[i][j]=max(f[i][j],f[i][j-1])\)

比賽總結

比賽的時候想到了DP
但是覺得可能是我不會的DP就放棄了
實際上十分簡單
不能知難而退,應該知難而進

Code

#include<bits/stdc++.h>
using namespace std;
int n,v,p,t,x,y,f[55][100005];
int read()
{
	int res=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch-'0'),ch=getchar();
	return res;	
}
int main()
{
	freopen("vidgame.in","r",stdin);
	freopen("vidgame.out","w",stdout);
	n=read();v=read();
	for (int i=1;i<=n;++i)
	{
		p=read();t=read();
		for (int j=p;j<=v;++j) f[i][j]=f[i-1][j-p];
		for (int j=1;j<=t;++j)
		{
			x=read();y=read();
			for (int j=v;j>=x+p;--j) f[i][j]=max(f[i][j],f[i][j-x]+y);
		}
		for (int j=0;j<=v;++j) f[i][j]=max(f[i][j],f[i-1][j]);
	}
	printf("%d\n",f[n][v]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}