01背包
0/1背包【基础算法・动态规划】——中高级
Time Limit: 1000MS | Memory Limit: 1000K | |
Total Submissions: 576 | Accepted: 308 |
Description
一个旅行者有一个最多能装m公斤的背包,现有n件物品,它们的重量分别是w1,w2,w3,...,wn,它们的价值分别为c1,c2,c3,...,cn。若每种物品只有一件,求旅行者能获得的最大总价值。
Input
m,和n(m<=200, n<=30)
接下来共n行每行两个整数wi,ci
Output
最大总价值
Sample Input
10 4
2 1
3 3
4 5
7 9
Sample Output
12
列出表格,找规律
v | w | id | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
2 | 6 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 |
2 | 3 | 2 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 4 |
6 | 5 | 3 | 0 | 0 | 0 | 2 | 2 | 6 | 6 | 6 | 8 | 8 | 8 |
5 | 4 | 4 | 0 | 0 | 0 | 2 | 5 | 5 | 5 | 7 | 8 | 11 | 11 |
4 | 6 | 5 | 0 | 0 | 0 | 2 | 5 | 5 | 5 | 7 | 8 | 11 | 11 |
得到如下公式:
\[
dp[i][j]=
\begin{cases}
max\{dp[i-1][j],v_i+dp[i-1][j-w_i]\},\quad \ \ & w_i\leq j,\\
dp[i-1][j], \quad \ \ & j<w_i,
\end{cases}
\]
AC代码如下:
1 /*01背包*/ 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 int v[35],w[35]; 9 int dp[35][205]; 10 11 int main() 12 { 13 int m,n; 14 scanf("%d%d",&m,&n); 15 for(int i=1;i<=n;i++) 16 scanf("%d%d",&w[i],&v[i]); 17 for(int i=1;i<=n;i++) 18 { 19 if(w[i]>m) 20 { 21 for(int j=1;j<=m;j++) 22 dp[i][j]=dp[i-1][j]; 23 continue; 24 } 25 for(int j=1;j<w[i];j++) 26 dp[i][j]=dp[i-1][j]; 27 for(int j=w[i];j<=m;j++) 28 dp[i][j]=max(dp[i-1][j],v[i]+dp[i-1][j-w[i]]); 29 } 30 printf("%d\n",dp[n][m]); 31 return 0; 32 }