1. 程式人生 > >挑戰程式設計 初級篇 動態規劃

挑戰程式設計 初級篇 動態規劃

1.01揹包問題

1.樸素的二維陣列解法

dp[i][j]表示前i件物品裝入容量是j的揹包所能獲得的最大價值

狀態轉移方程是dp[i][j]=(1)dp[i-1][j](在第i件物品裝不下的情況下)

(2)max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])(裝的下的情況下,裝和不裝都試一下)

#include<iostream>
using namespace std;
int n,w[100],v[100],dp[100][10000],ww;//w表示重量,v表示價值
void solve()
{
    int i,j;
    cin>>n>>ww;//
ww是揹包容量 for(i=1;i<=n;i++)cin>>w[i];//輸入n個物品的重量 for(i=1;i<=n;i++)cin>>v[i];//輸入n個物品的價值 for(i=1;i<=n;i++) for(j=1;j<=ww;j++) { if(j<w[i])dp[i][j]=dp[i][j-1];//如果放不下的話就不放 else dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);//放的下的話,選放和不放的最大值
} cout<<dp[n][ww]<<endl;//n個物品,容量是ww的揹包能裝下的最大價值 } int main() { solve(); }
View Code

2.滾動陣列的解法

滾動陣列的解法時間複雜度沒有變化,都是O(n*ww),但是減少了空間複雜度

狀態轉移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i])(max裡的dp[j]表示前i-1件物品裝入容量j的揹包獲得的最大價值)

#include<iostream>
using namespace std;
int ww,n,w[100],v[100],dp[10000];//n個物品,揹包容量ww void solve() { int i,j; cin>>n>>ww; for(i=1;i<=n;i++)cin>>w[i]; for(i=1;i<=n;i++)cin>>v[i]; for(i=1;i<=n;i++) for(j=ww;j>=w[i];j--)//這種情況下一定裝的下(裝不下的情況就是dp[j]=dp[j]所以不加if判斷) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); cout<<dp[ww]<<endl; } int main() { solve(); }
View Code

3.揹包容量可能特別大的情況