开始认真学DP。我对滚动数组的理解是:后一个状态可以由前一个状态求得,便可以使用一维数组重复利用节省空间复杂度。
这个题要注意题目要求的前提,求次数可以看作重量为v[i]价值为1放入w-1的背包,歌曲就是重量和价值都是v[i],简单的转化。
#include <iostream> #include <bits/stdc++.h> using namespace std; const int maxn = 100000+10; int dp[maxn]; int v[maxn]; int cnt[maxn]; int main() { int t; cin >> t; int kase = 0; while(t--) { int n,w; cin >> n >> w; for(int i = 1 ; i <= n ; i ++) cin >> v[i]; printf("Case %d:",++kase); memset(dp,0,sizeof(dp)); memset(cnt,0,sizeof(cnt)); for(int i = 1 ; i <= n ; i++) { for(int j = w-1 ; j >= v[i] ; j--) { if(cnt[j] < cnt[j - v[i]]+1) { dp[j] = dp[j-v[i]]+v[i]; cnt[j] = cnt[j-v[i]]+1; } else if(cnt[j] == cnt[j-v[i]]+1) dp[j] = max(dp[j],dp[j-v[i]]+v[i]); } } cout << " " << cnt[w-1]+1 << " " << dp[w-1]+678 << endl; } return 0; }
时间: 2024-10-14 20:16:04