zoukankan      html  css  js  c++  java
  • ACM_01背包

    背包1

    Time Limit: 2000/1000ms (Java/Others)

    Problem Description:

    有n个重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总量不超过 W 的物品,求所有方案中价值总和的最大值。

    Input:

    输入包含多组测试用例,每一例的开头为两位整数 n、W(1<=n<=10000,1<=W<=1000),接下来有 n 行,每一行有两位整数 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)。

    Output:

    输出为一行,即所有方案中价值总和的最大值。

    Sample Input:

    3 4
    1 2
    2 5
    3 7

    Sample Output:

    9
    解题思路:简单的01背包,一维滚动数组实现,空间优化到O(W),时间复杂度仍为O(nW)。通过二维数组的计算过程中可以发现:第i件物品放与不放的结果dp[i,j]只与上一个状态的计算结果dp[i-1,j]和dp[i-1,j-wi]有关,而前面储存的信息dp[0~i-2,jor(j-wi)]再也没有用到了,那就将其舍弃,换用一维数组dp[j]来代表dp[i,j]。由二维数组状态转移方程dp[i,j]=max(dp[i-1,j],dp[i-1,j-wi]+vi)可得一维数组状态转移方程dp[j]=max(dp[j],dp[j-wi]+vi)。注意:第二重循环要逆序枚举W~w[i],这样才保证了每件物品只被拿一次,即保证了计算dp[j]时dp[j-wi]保存的是上一个状态dp[i-1,j-wi]的值,而不是当前状态dp[i][j-wi]的值,这个不难证明可以手动模拟一下。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=10005;
     4 int n,W,v[maxn],w[maxn],dp[maxn];//dp数组始终记录当前体积的最大价值
     5 int main(){
     6     while(cin>>n>>W){
     7         for(int i=0;i<n;i++)
     8             cin>>w[i]>>v[i];
     9         memset(dp,0,sizeof(dp));
    10         for(int i=0;i<n;++i)   //个数
    11             for(int j=W;j>=w[i];--j) //01背包
    12                 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); //比较放入i物体后的价值与不放之前的价值,记录大的值
    13         cout<<dp[W]<<endl;//输出总体积的最大值
    14     }
    15     return 0;
    16 }
  • 相关阅读:
    python-异常处理总结
    python-笔记-内置函数
    python练习题--计算总分平均分操作excel
    python-笔记(操作excel)
    python -加密(MD5)
    jmeter-http信息头管理器
    python-判断一个字符串是不是小数
    [Python] [Django] Django将post请求变成get
    离线安装rabbitmq
    python第三方包的几种安装方式
  • 原文地址:https://www.cnblogs.com/acgoto/p/8995090.html
Copyright © 2011-2022 走看看