标签:
背包问题:
首先我们考虑暴力法:每种情况试一下看看最小。这样的每层递归要分两次,为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 }
然后我们再来想:画它的递归树会发现有很多重复的不需要第二次计算的东西
所以我们开一个数组来储存它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 }
标签:
原文地址:http://www.cnblogs.com/do-it-best/p/5465513.html