码迷,mamicode.com
首页 > 其他好文 > 详细

挑战程序设计竞赛 dp

时间:2016-05-06 14:43:09      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

背包问题:

首先我们考虑暴力法:每种情况试一下看看最小。这样的每层递归要分两次,为O(2^n)

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 #define maxn 105
 6 int n,W;
 7 int w[maxn],v[maxn];
 8 
 9 int rec(int i,int j)
10 {
11     int res;
12     if(i==n) res=0;
13     else if(j<w[i]) res=rec(i+1,j);
14     else res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
15     return res;
16 }
17 
18 int main()
19 {
20     scanf("%d",&n);
21     for(int i=0;i<n;i++)
22         scanf("%d%d",&w[i],&v[i]);
23     scanf("%d",&W);
24     printf("%d\n",rec(0,W));
25 }
View Code

 

然后我们再来想:画它的递归树会发现有很多重复的不需要第二次计算的东西

所以我们开一个数组来储存它dp[maxn+1][maxn+1]当他已经存在就不需要计算他了。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 #define maxn 105
 6 int n,W;
 7 int w[maxn],v[maxn];
 8 int dp[maxn+1][maxn+1];
 9 
10 int rec(int i,int j)
11 {
12     int res;
13     if(i==n) res=0;
14     else if(j<w[i]) res=rec(i+1,j);
15     else res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
16     return res;
17 }
18 
19 int main()
20 {
21     scanf("%d",&n);
22     for(int i=0;i<n;i++)
23         scanf("%d%d",&w[i],&v[i]);
24     scanf("%d",&W);
25     memset(dp,-1,sizeof(dp));
26     printf("%d\n",rec(0,W));
27 }
View Code

 

挑战程序设计竞赛 dp

标签:

原文地址:http://www.cnblogs.com/do-it-best/p/5465513.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!