HDU ACM 4501 小明系列故事——买年货->多维双肩包(多为01背包)

HDU ACM 4501 小明系列故事——买年货->多维背包(多为01背包)

分析:dp[l][i][j][k]表示选前l件时花费i元,积分j,免费p时能获得的最大价值。k值也作为一种背包算。

状态转移方程:
dp[l][i][j][k] = max(dp[l][i][j][k], dp[l-1][i-a[l]][j][k]+c[i], dp[l-1][i][j-b[l]][k]+c[i], dp[l-1][i][i][k-1]+c[i])  (k > 0, i >= a[l] , j >= b[l], k= 1,2,3,4....n)
a[l]表示第l种用现金要的的钱数,b[l]表示第l种用积分兑换需要花的积分数。

#include<iostream>
using namespace std;

int dp[101][101][6];  //dp[l][i][j][k],表示选l件商品花费i元,j积分,p免费是获得的最大价值,滚动数组减一维
int a[101],b[101],c[101];
int n,v1,v2,k;
#define max(a,b) ((a)>(b)?(a):(b))

int sovle()
{
	int i,j,kk,l,ans;

	memset(dp,0,sizeof(dp));
	for(i=0;i<n;i++)
		for(j=v1;j>=0;j--)
			for(kk=v2;kk>=0;kk--)
				for(l=k;l>=0;l--)
				{
					ans=0;
					if(j>=a[i])
						ans=max(ans,dp[j-a[i]][kk][l]+c[i]);
					if(kk>=b[i])
						ans=max(ans,dp[j][kk-b[i]][l]+c[i]);
					if(l>=1)
						ans=max(ans,dp[j][kk][l-1]+c[i]);
					dp[j][kk][l]=max(ans,dp[j][kk][l]);
				}
	return dp[v1][v2][k];
}

int main()
{
	int i;

	while(cin>>n>>v1>>v2>>k)
	{
		for(i=0;i<n;i++)
			cin>>a[i]>>b[i]>>c[i];
		cout<<sovle()<<endl;
	}
    return 0;
}