1. 程式人生 > >1091-還是01揹包(入門)

1091-還是01揹包(入門)

1091-還是01揹包

 

  • 記憶體限制:223MB 時間限制:10000ms 特判: No
  •  
  • 通過數:1 提交數:1 難度:5


 

題目描述:

有n個重量和價值分別為 wi 和 vi 的物品,從這些物品中挑選總重量不超過W的物品,求所有挑選方案中價值總和的最大值。

輸入描述:

多組測試資料。
每組測試資料第一行輸入n 和 W ,接下來有n行,每行輸入兩個數,代表第i個物品的wi 和 vi。
1 <= n <=40
1 <= wi <= 10^15
1 <= vi <= 10^15
1 <= W <= 10^15

輸出描述:

每組資料輸出一行,代表挑選方案中價值總和的最大值。

樣例輸入:

複製

4 5
2 3
1 2
3 4
2 2

樣例輸出:

7

這題是在01揹包改了一下。這次不妨用dp針對不同價值計算最小的重量。dp[j]=min(dp[j],dp[j-v[i]]+w[i]), j<=n*maxx,  

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
ll dp[maxn];
ll wei[maxn],v[maxn];
const int inf=0x3f3f3f3f;
int main()
{
	ll n,w;
	int t;
	while(~scanf("%lld%lld",&n,&w))
	{
		memset(dp,inf,sizeof(dp));
		ll mx=-1;
		for(int i=0;i<n;i++) 
		{
			scanf("%lld%lld",&wei[i],&v[i]);
			mx=max(mx,v[i]);
		}
		dp[0]=0;
		
		for(int i=0;i<n;i++)
		for(int j=n*mx;j>=v[i];j--)
		{
			dp[j]=min(dp[j],dp[j-v[i]]+wei[i]);
		}
		ll j;
		
		for(j=n*mx;j>=0&&dp[j]>w;j--); 
		printf("%lld\n",j);
	}
 } 


改的很巧,既然重量太大,那就dp[j]中j代表著價值,找j價值的最小重量,然後只需找出dp[j]<=W的最大j。出口是dp[0]=0;