1. 程式人生 > >疊放箱子問題(方法二)【DP】

疊放箱子問題(方法二)【DP】

題目見:疊放箱子問題(方法一)【DP】


> 解題思路
這一道題比第一種方法更加優化。
f[i][j]表示前i個箱子排j個的最小總重量(這裡的前i個箱子還是倒著來的,為從第i個箱子到第n個箱子),要求最小總重量是因為為了能讓接下來的一個箱子有更多重量去裝更多的箱子。

狀態轉移方程:

f[i][j]=min(f[i][j],f[i-1][j-1]+w[i])

輸出的時候就是for語句(倒著)迴圈一下,如果迴圈到第一個f[1][i]的重量有存入過,就直接退出,輸出i的值。

感性理解一下


> 程式碼

#include<iostream>
#include<cstdio> #include<algorithm> using namespace std; int n,f[1005][1005]={0},w[1005],c[1005]={0}; //w陣列存箱子自身重量,c陣列存箱子承受重量 int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=6000; //設標誌(其實可以用inf,但是我不知道為什麼我用inf會出錯)
f[n][0]=0; f[n][1]=w[n]; for(int i=n-1;i>=1;i--) for(int j=0;j<=n-i+1;j++) //j<=n-i+1為從i到n的箱子總個數 { f[i][j]=f[i+1][j]; if((f[i+1][j-1]<=c[i])&&(j!=0)) //如題描述,不能超過承受重量 f[i][j]=min(f[i][j],f[i+1][j-1]+w[i]); } int ans; for(ans=n;ans>=0;ans--) if(f[1][ans]!=6000) break
; printf("%d",ans); return 0; }