• 动态规划:背包问题


    背包问题  

    • 有一个背包(限定条件:对可选的东西进行限制),从一堆物品中选择若干放进背包,使得最后背包中的价值是最大的
    • 01背包:对于一个物品,可以选0或1    
    • 完全背包:对于一个物品,可以选多次(>=1)  

    01背包 

    1. 问题描述 http://hihocoder.com/problemset/problem/1038

    有M张奖券,奖品区有N件奖品,分别标号为1到N,其中第i件奖品需要need(i)张奖券进行兑换且评分值为value(i)。每件奖品最多只能兑换一次。凭借他手上的M张奖券,可以换到哪些奖品,使得这些奖品的喜好值之和能够最大。

    奖品标号 1 ... i ... N
    需要奖券 need(1) ... need(i) ... need(N)
    评分值 value(1) ... value(i) ... value(N)

    2. 状态转换

    • 状态:allValue[i][j] = 喜好总值[当前是第i件物品][前面已经使用的奖券j]
    • 决策:第i件物品是否要选
    • 状态转换: allValue[i][j] = max{allValue[i - 1][j], allValue[i - 1][j - need[i]] + value[i]}
    • 从左往右,从下往上 for(...i...){for(...j...)}

    3. 代码

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<stdio.h>
     4 int dp[505][100005];
     5 int w[505],v[505];
     6 int max(int m,int n)
     7 {
     8     return m>n?m:n;
     9 }
    10 void solve(int n,int m)
    11 {
    12     int i,j;
    13     for(i=0;i<=m;i++)
    14         dp[0][i]=0;
    15     for(i=0; i<n; i++)
    16         for(j=0; j<=m; j++)
    17         {
    18             if(j<w[i])
    19                 dp[i+1][j]=dp[i][j];
    20             else
    21                 dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
    22         }
    23         printf("%d",dp[n][m]);
    24 }
    25 int main()
    26 {
    27     int n,m,i;
    28     scanf("%d%d",&n,&m);
    29     for(i=0;i<n;i++)
    30             scanf("%d%d",&w[i],&v[i]);
    31     solve(n,m);
    32     return 0;
    33 } 
    View Code

    完全背包 

    1. 问题描述 http://hihocoder.com/problemset/problem/1043

    可以兑换无数次

    2. 状态转换

    • 状态:allValue[i][j] = 喜好总值[当前是第i件物品][前面已经使用的奖券j]
    • 决策:第i件物品可以选k件(0<=k<=剩余的奖券/第i件物品需要的)
    • 状态转换: allValue[i][j] = max{allValue[i - 1][j - k*need[i]] + k*value[i]}
    • 优化转换关系:
      • 在对j的遍历过程中,会先后计算到allValue[i][j-need[i]], allValue[i][j]
      • 1) allValue[i][j] = max{allValue[i-1][j], allValue[i-1][j-need[i]] + value[i], ...,allValue[i-1][j-k*need[i]]+k*value[i]}
      • 2)allValue[i][j - need[i]] = max{allValue[i-1][j-need[i]] + value[i], ...,allValue[i-1][j-k'*need[i]]+k'*value[i]}
      • 1)2)可以转换成:allValue[i][j] = max{allValue[i-1][j], allValue[i][j - need[i]] + value[i]}

    3. 代码

     1 #include <iostream>
     2 using namespace std;
     3 const int maxN = 501;
     4 const int maxM = 100001;
     5 int values[maxN][maxM];
     6 struct Prize
     7 {
     8     int need;
     9     int value;
    10 }prizes[maxN];
    11 
    12 
    13 void dp(int N, int M)
    14 {
    15     for (int i = 0; i <= M; i++)
    16         if (i >= prizes[0].need)
    17             values[0][i] = i / prizes[0].need * prizes[0].value;
    18         else
    19             values[0][i] = 0;
    20     int max = 0;
    21     for (int i = 1; i < N; i++)
    22     {
    23         for (int j = 0; j <= M; j++)
    24         {
    25             if (prizes[i].need > j)
    26                 values[i][j] = values[i - 1][j];
    27             else
    28             {
    29                 int tmp = values[i][j - prizes[i].need] + prizes[i].value;
    30                 if (tmp > values[i - 1][j])
    31                     values[i][j] = tmp;
    32                 else
    33                     values[i][j] = values[i - 1][j];
    34             }
    35         }
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     int M, N;
    42     cin >> N >> M;
    43     for (int i = 0; i < N; i++)
    44         cin >> prizes[i].need >> prizes[i].value;
    45     prizes[N].need = prizes[N].value = 0;
    46     
    47     dp(N, M);    
    48     cout << values[N - 1][M] << endl;
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    JDK源码之Thread 类分析
    java中符号类型和无符号类型的问题分析
    国内高速Maven仓库
    Idea Live Templates代码模板
    正则表达式
    java内存泄漏
    MySQL查看 InnoDB表中每个索引的高度
    ThreadLocalMap里Entry为何声明为WeakReference?
    Java JDBC中,MySQL字段类型到JAVA类型的转换
    MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现
  • 原文地址:https://www.cnblogs.com/coolqiyu/p/5960565.html
Copyright © 2020-2023  润新知