zoukankan      html  css  js  c++  java
  • 0-1背包问题,附上例题(POJ

    0-1背包问题的题目样式

    有 N 件物品和一个容量为 M 的背包。放入第 i 件物品耗费的费用是 Wi,得到的价值是 Vi。求解将哪些物品装入背包可使价值总和最大。

    0-1背包问题关键在于该物品放或不放,即在当前容量为M的的情况下,选择不选择该物品,那么就有一个转移方程

    for(i=0  -  N)

      for(j= M - w[i])

        dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);

    当前物品为i,当前的背包容量为j,如果不选当前该物品,则选取dp[i-1][j]该值。如果选择当前物品,则选取dp[i-1][j+w[i]]+v[i]该值,从两个值当中选取大的值。

    最后在dp[N][]中选出最大的,为总和最大的答案

    0-1背包的方程优化

      上一个转移方程解法,在时间上已基本无法优化,只能在空间上进行优化。从O(NM)-> O(M)

    转移方程变为

    for(j=M  -  w[i])

      dp[j] = max(dp[j],dp[j-w[i]]+v[i]);

    下面解释一下为什么该方程可行:

    因为w[i]是个正数,即j+w[i] > j肯定是成立的,j <=j 且j <=j+w[i],所以对于下一次循环j+1肯定不会取到j+1之前的值,所以该转移方程对后续没有影响,是成立的。

    最后找出dp[]中最大的就行

    给出一道0-1背包的例题

    POJ - 3624    http://poj.org/problem?id=3624

         Charm Bracelet
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 40985   Accepted: 17828

    Description

    Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).

    Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

    Input

    * Line 1: Two space-separated integers: N and M
    * Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

    Output

    * Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

    Sample Input

    4 6
    1 4
    2 6
    3 12
    2 7

    Sample Output

    23

    未优化的代码,提交上去是(Memory Limit Exceeded),因为空间复杂度太大
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 int dp[3500][13000];
     7 int main()
     8 {
     9     int n , m ;
    10     int w[3500], v[3500];
    11 
    12     while(scanf("%d%d",&n,&m) != EOF) {
    13         for(int i= 1 ; i <= n ; i++)
    14             scanf("%d%d",&w[i],&v[i]);
    15         for(int i = 1 ; i <= n; i++) {
    16             for(int  j = 0; j <= m; j++) {
    17                 if(j+w[i] <= m)
    18                     dp[i][j] = max(dp[i-1][j],dp[i-1][j+w[i]]+v[i]);
    19                 else dp[i][j] = dp[i-1][j];
    20             }
    21         }
    22         int ans =0;
    23         for(int j = 0; j <= m; j++)
    24             ans = dp[n][j] > ans ? dp[n][j]:ans;
    25         printf("%d
    ",ans);
    26     }
    27     return 0;
    28 }
    
    
    



    下面给出优化的代码(accpeted)
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 int dp[13000];
     7 int main()
     8 {
     9     int n , m ;
    10     int w[3500], v[3500];
    11 
    12     while(scanf("%d%d",&n,&m) != EOF) {
    13         for(int i= 1 ; i <= n ; i++)
    14             scanf("%d%d",&w[i],&v[i]);
    15         for(int i = 1 ; i <= n; i++) {
    16             for(int  j = 0; j <= m; j++) {
    17                 if(j+w[i] <= m)
    18                     dp[j] = max(dp[j],dp[j+w[i]]+v[i]);
    19                 else dp[j] = dp[j];
    20             }
    21         }
    22         int ans =0;
    23         for(int j = 0; j <= m; j++)//
    24             ans = dp[j] > ans ? dp[j]:ans;
    25         printf("%d
    ",ans);
    26     }
    27     return 0;
    28 }
    
    
    
  • 相关阅读:
    批处理文件双击运行成功,程序调用却运行失败解决方案
    前端安全之加解密种类与HTTPS加密原理(二)
    node包管理nvm与pnpm(一)
    React状态管理—reduxAPI原理分析(三)
    动态规划原理与算法实践(二)
    双指针算法基本原理和实践(一)
    分治算法基本原理和实践(三)
    编程范式(一)
    Java基础
    前端模块化CommonJS、AMD、CMD、ES6模块(二)
  • 原文地址:https://www.cnblogs.com/creativepower/p/7395874.html
Copyright © 2011-2022 走看看