Hdu 5543 Pick The Sticks(01揹包變形)

傳送門

題意:給定n個長度爲v[i], 價值爲w[i]的木棍,問在總長度不超過l的情況下最大價值是多少。限制條件是:兩端的木棍可以一半在長度範圍內,一半在外面。



,,,快把評測姬wa穿了也沒做出來,,白做那麼多揹包的題了,,,生氣

思路:最多兩個木棍可以一半長度在裏面,那麼放長度爲一半的木棍的時候必須確保狀態轉移的時候不能從之前放的已經有兩個木棍放了一半的情況下轉移,,我試圖用一維dp做,,結果,我不wa誰wa。

dp[j][k]表示揹包剩餘容量爲j,放了k個一半長度的木棍在揹包裏的最大價值
(0<=j<=l, 0<=k<3)

但是還有一個問題,如果木棍長度爲奇數,我們讓v[i]/2在裏面還是v[i]/2+1在裏面?事實上都不對,,,它的一半就是準準確確的一半,那麼就把所有的長度都乘以2,就不會出現這種問題了。(我爲啥就想不到,枯了)

代碼:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 2005;
ll v[N],dp[N<<1][5],w[N];
int main()
{
	int t,cas=1;
	cin>>t;
	while(t--)
	{
		int n,l;
		ll ans=0;
		cin>>n>>l;
		l*=2;
		for(int i=0;i<n;i++) scanf("%lld%lld",&v[i],&w[i]),v[i]*=2;
		memset(dp,0,sizeof dp);
		for(int i=0;i<n;i++)
		{
			for(int j=l;j>=0;j--)
				for(int k=0;k<3;k++)
				{
					if(j>=v[i])
						dp[j][k]=max(dp[j][k],dp[j-v[i]][k]+w[i]);
					if(k&&j>=v[i]/2)
						dp[j][k]=max(dp[j][k],dp[j-v[i]/2][k-1]+w[i]);
				}
		}
		for(int i=0;i<n;i++) ans=max(ans,w[i]);
		for(int k=0;k<3;k++) 
			ans=max(ans,dp[l][k]);
		printf("Case #%d: ",cas++);
		cout<<ans<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章