zoj4019 Schrödinger's Knapsack(状压dp)
题意:有两种物品分别为n,m个,每种物品对应价值k1,k2。有一个容量为c的背包,每次将一个物品放入背包所获取的价值为k1/k2*放入物品后的剩余体积。求问所获取的最大价值。
整体来看,优先放入体积较小的物品所获取的价值会更大。但是有两种物品,k1,k2不同,所以还需要考虑放入两种物品的先后。那么,可以写成状态转移方程,dp[i][j]=max(dp[i-1][j]+k1*(c-suma[i]-sumb[j]),dp[i][j-1]+k2*(c-suma[i]-sumb[j])),方程代表在先放入第一种物品的第i个,或第二种物品的第j个中选取更优的情况。
PS.没有dp数组清零,导致wa。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #define maxn 2005 5 using namespace std; 6 long long a[maxn],b[maxn],suma[maxn],sumb[maxn]; 7 long long dp[maxn][maxn]; 8 int k1,k2,c; 9 int n,m; 10 int main(){ 11 int t; 12 cin >> t; 13 while (t--){ 14 cin >> k1 >> k2 >> c; 15 cin >> n >> m; 16 for (int i=1;i<=n;i++) cin >> a[i]; 17 for (int i=1;i<=m;i++) cin >> b[i]; 18 a[0]=0;b[0]=0;suma[0]=0;sumb[0]=0; 19 sort(a+1,a+1+n); 20 sort(b+1,b+1+m); 21 for (int i=1;i<=n;i++){ 22 suma[i]=suma[i-1]+a[i]; 23 } 24 for (int i=1;i<=m;i++){ 25 sumb[i]=sumb[i-1]+b[i]; 26 } 27 28 long long ans=0; 29 for (int i=0;i<=n;i++){ 30 for (int j=0;j<=m;j++){ 31 dp[i][j]=0; 32 } 33 } 34 for (int i=1;i<=n;i++){ 35 dp[i][0]=dp[i-1][0]+k1*(c-suma[i]); 36 ans=max(ans,dp[i][0]); 37 } 38 for (int j=1;j<=m;j++){ 39 dp[0][j]=dp[0][j-1]+k2*(c-sumb[j]); 40 ans=max(ans,dp[0][j]); 41 } 42 for (int i=1;i<=n;i++){ 43 for (int j=1;j<=m;j++){ 44 long long tmp=suma[i]+sumb[j]; 45 if (tmp<=c) 46 dp[i][j]=max(dp[i-1][j]+k1*(c-tmp),dp[i][j-1]+k2*(c-tmp)); //先选取第一种物品中的第i个,或第二种物品中的第j个 47 ans=max(ans,dp[i][j]); 48 } 49 } 50 51 cout << ans << endl; 52 } 53 return 0; 54 }