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  }

 

你可能感兴趣的:(dp)