1. 程式人生 > >NYOJ 654喜歡玩warcraft的ltl(01背包/常數級優化)

NYOJ 654喜歡玩warcraft的ltl(01背包/常數級優化)

擁有 pre true enc light mil tro acm 道具

傳送門

Description

ltl 非常喜歡玩warcraft,因為warcraft十分講究團隊整體實力,而他自己現在也為升級而不拖累團隊而努力。

他現在有很多個地點來選擇去刷怪升級,但是在每一個地點他都要買上充足的補給和合適的道具,以免在刷怪的時候被怪物反殺了,每一個地點的怪物打完了就沒有了(還居然不掉金錢跟裝備),而且他只要選定了地點就一定會刷完該地點全部的怪物,同時獲得對應的經驗值。現在ltl 能給出每一個地點用來買補給和道具的錢和打完全部怪物所能獲得的經驗,但是他所擁有的錢是一定的。所以他想知道怎麽選擇地點使得他獲得的經驗最高。

Input

第一行一個整數T,表示測試數據的組數 0<T<=10


第二行兩個整數N,M,0<N<=100,0<M<=1000000表示ltl擁有N個不同地點的選擇和M的金錢總數
接下來N行每行兩個整數ci,vi,(0<ci<=1000000,0<vi<=2000)表示ltl刷完第i個地點所需要購買補給和道具的總錢數和能獲取的總經驗值

Output

一行一個整數,表示ltl能夠獲取的最大的經驗值

Sample Input

2
3 10
7 7
2 3
3 5
2 5
3 5
2 1

Sample Output

Max experience: 12
Max experience: 6

思路

01背包問題,主要是常數級的優化。我們所要求的就是f[v],而對於f[v]和最後一件要放入的物品n來說,只需要知道f[v-cn]是多少就行;於是,同理,對技術分享

和物品n-1來說,需要的是技術分享
於是,到物品i,也就是物品n-(n-i),需要的就是技術分享。然而,有的物品可能是不會放進去的而且f[-1]是不存在的,於是,max{V-sum{c[i..n]},c[i]}。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 105;
int c[maxn],v[maxn];
int dp[1000005];

int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int N,M;
		memset(dp,0,sizeof(dp)); 
		scanf("%d%d",&N,&M);
		for (int i = 1;i <= N;i++)	scanf("%d%d",&c[i],&v[i]);
		for (int i = 1;i <= N;i++)
		{
			int tmp = 0;
			for (int j = i + 1;j <= N;j++)	tmp += c[j];
			tmp = max(M-tmp,c[i]);      //01背包常數級優化 
			for (int j = M;j >= tmp;j--)
			{
				dp[j] = max(dp[j],dp[j-c[i]]+v[i]);
			}
		}
		printf("Max experience: %d\n",dp[M]);
	}
	return 0; 
} 

  

NYOJ 654喜歡玩warcraft的ltl(01背包/常數級優化)