1. 程式人生 > >【WOJ 3966】lzy的遊戲

【WOJ 3966】lzy的遊戲

【題目】

題目描述:

Leo 最近迷上卡牌遊戲,他手上有 nn 張卡牌,每張卡牌有 22 個屬性分別是傷害值 did_i,魔法值 lil_i

玩遊戲時,他把卡牌按順序放在手上,然後每一次他可以選擇將最上面在牌打出去,造成 did_i 在傷害,同時會消耗 lil_i 張牌(最上面在 lil_i 張,包括最上面一張,如果手上在牌不足 lil_i 張則不能打出最上面的牌)。如果他不想(不能)打出目前最上面在牌,他可以將最上面在牌放到最下面去。LZY 肯定希望對敵人造成最大的傷害,希望你幫他計算能造成在最大傷害。

輸入格式:

第一行是一個數字 nn

接下來 n

n 行,每行 22 個數字 did_ilil_i 表示每張牌的 22 個屬性

輸出格式:

輸出一行僅一個數,表示最大傷害

樣例資料:

輸入 5 2 1 5 3 4 2 1 2 3 1

輸出 10

備註:

【資料規模和約定】 對於 30%30\% 的資料,11nn202011lil_i2020 對於 100%100\% 的資料,11nn1000100011lil_i10010011did_i1000010000

【分析】

口胡一下正解吧(有一些神奇的證明我也不會)

首先是所有要選的牌的 lil_i 之和應該小於等於 n

n(應該是很顯然的)

然後就是對於任意一組和 lil_i 小於等於 nn 的方案,我們總能夠通過調整打牌的順序來打出這一組牌(感性理解)

這樣的話,將 did_i 看做價值,將 lil_i 看做價格,直接用0101揹包做就行了

我覺得是非常妙的轉化啊

【程式碼】

#include<cstdio>
#include<algorithm>
#define N 1005
using namespace std;
int f[N];
int main()
{
	int n,i,j,d,l;
	scanf("%d",&n);
	for(i=1;i<=
n;++i) { scanf("%d%d",&d,&l); for(j=n;j>=l;--j) f[j]=max(f[j],f[j-l]+d); } printf("%d",f[n]); return 0; }