NYOJ 49 开心的小明 (dp问题之01背包问题)

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=49

思路:01背包问题

   考虑使用dp问题 求解,定义一个递归式 opt[i][v] 表示前i个物品,在背包容量大小为v的情况下,最大的装载量。
     opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])   //w[i]是容量为c[i]时的装载量
   解释如下:
     opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int f[30001];
 5 int main()
 6 {
 7     int i,T,n,m,v,w;
 8      cin>>T;
 9      while(T--)
10      {
11          cin>>n>>m;     //输入总钱数和物品最大个数 
12          memset(f,0,sizeof(f));
13          while(m--)
14          {
15              cin>>v>>w;   //输入每个物品的价格和权值 
16              for(i=n;i>=v;i--)
17              f[i]=max(f[i],f[i-v]+w*v);  //这点是关键,f[i]表示当前容量为i时乘过权值的价格,f[i-v]+w*v表示在i-v这个容量时加上w*v与此时的f[i]容量相比较,取最大值,即最优解,转化为01背包问题去思考,
18          }
19          cout<<f[n]<<endl; 
20      }
21      return 0;
22 }

 

 

别人的思路:

分析:01背包;d[i][j]表示在前 i 个物品中选择一些物品放入容量为 j 的背包中 第 i 个物体有放和不放两种情况                   

不放:就相当于在前 i-1 个物品中选择 即 d[i-1][j];                      

 放:就是前 i-1 个物品只有 j-v 的容量让放 即 d[i-1][j-v]+w;                  

综合两种情况的最优是 d[i][j]=max{d[i-1][j] , d[i-1][j-v]+w};        

空间优化如下:       

d[i]表示容量为 i 的最优值,a[]表示物品的重量,b[]表示对应的价值量;      

d[i]=max(d[i] , d[i-a[i]] + a[i]*b[i]);

 1  #include<iostream>
 2  #include<cstring>
 3  #define M 30010
 4  #define N 30
 5  using namespace std;
 6  
 7  int d[M],a[N],b[N];
 8  
 9  int max(int x,int y)
10  {
11      return x>y?x:y;
12  }
13  
14  int main()
15  {
16      int test,m,n,i,j;
17      cin>>test;
18      while(test--)
19      {
20          cin>>m>>n;
21          for(i=1;i<=n;i++) cin>>a[i]>>b[i];
22          memset(d,0,sizeof(d));
23          for(i=1;i<=n;i++)
24          {
25              for(j=m;j>=a[i];j--)
26              {
27                  d[j]=max(d[j],d[j-a[i]]+a[i]*b[i]);
28              }
29          }
30          cout<<d[m]<<endl;
31      }
32      return 0;
33  }

 

posted on 2012-08-14 08:36  mycapple  阅读(1336)  评论(0编辑  收藏  举报

导航