背景:沒有認真讀題目條件,搞錯輸入順序而wa了一次。自己做的第一道DP題,看了好久終於把背包九講的01背包看懂了。
學習:
1.01背包的特點是:物品個數有限,切對於每一個物品可以選擇放或者不放。其中的名稱01,大概就是1(放)0(不放)的意思吧。
傳統的背包寫法使用二維數組,時間和空間都是O(VN),當把j由0.....n,換為n.....0之後空間優化為O(V),然後做了兩點剪枝,這裡解釋一下剪枝的原理:
int min=max(list[1][i],v-sum(i,n-1));分析:剪枝的具體方法如上就是將,j的循環下限為0,改成min。其中list[1][i]為當前選擇物品(第i個物品)的花費,如果剩下的余下的體積已經小於list[1][i],說明無論如何
#includeusing namespace std; int list[2][1000],F[1001]; int sum(int i,int k){ int ans=0; for(int j=i;j <= k;j++) ans+=list[1][j]; return ans; } void dp(void){ int v,n; cin >> n >> v; for(int i=0;i < v+1;i++) F[i]=0; for(int i=0;i < 2;i++) for(int j=0;j < n;j++) cin >> list[i][j]; for(int i=0;i < n;i++){ int min=max(list[1][i],v-sum(i,n-1)); for(int j=v;j >= min;j--) F[j]=max(F[j],F[j-list[1][i]]+list[0][i]); } cout << F[v] << endl; } int main(void){ int tests; cin >> tests; while (tests--) dp(); return 0; }