zoukankan      html  css  js  c++  java
  • 动态规划入门-01背包问题

    2017-08-12 18:50:13

    writer:pprp

    对于最基础的动态规划01背包问题,都花了我好长时间去理解;

    poj3624是一个最基本的01背包问题:

    题意:给你N个物品,给你一个容量为M的背包

      给你每个物品的重量,Wi

      给你每个物品的价值,Di

      求解在该容量下的物品最高价值?

    分析:

      状态:

        dp[i][j] = a 剩下i件 当前容量为j的情况下的最大价值为a

      如果用 i 来枚举物品编号, 用 j 来枚举重量,那么 

        if ( j is from 1 to weight[i] )  dp[i][j] = dp[i-1][j];

        if( j is from weight[i] to M) dp[i][j] = max{ dp[i-1][j] , dp[i-1][j - weight[i]] + value[i]}


    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    
    using namespace std;
    
    const int maxnp = 3500;
    const int maxnw = 13000;
    int dp[maxnp][maxnw];
    int value[maxnp];
    int weight[maxnw];
    int N, M;
    
    void output();
    
    void solve()
    {
        memset(dp,0,sizeof(dp));
    
        for(int i = 1 ; i <= N ; i++)
        {
            for(int j = 1 ; j < weight[i] ; j++)
                dp[i][j] = dp[i-1][j];
            for(int v = weight[i] ; v <= M ; v++)
            {
                dp[i][v] = max(dp[i-1][v],dp[i-1][v-weight[i]]+value[i]);
            }
        }
    }
    
    int main()
    {
        cin >> N >> M;
    
        for(int i = 1 ; i <= N; i++)
        {
            cin >> weight[i] >> value[i];
        }
    
        solve();
    
        cout << dp[N][M] <<endl;
    }

    然后可以从上边的这个部分:

    for(int j = 1 ; j < weight[i] ; j++)
                dp[i][j] = dp[i-1][j];
            for(int v = weight[i] ; v <= M ; v++)
            {
                dp[i][v] = max(dp[i-1][v],dp[i-1][v-weight[i]]+value[i]);
            }

    看出来有点冗余复杂,出现了MLE

    现在重新定义一个状态:dp[i]表示重量剩余 i 的时候可以得到的最大价值

    状态转移:dp[i] = max(dp[i], dp[i-weigth[j]]+value[j]);

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    
    using namespace std;
    
    const int maxnp = 3500;
    const int maxnw = 13000;
    int dp[maxnw];
    int value[maxnp];
    int weight[maxnw];
    int N, M;
    
    void solve()
    {
          memset(dp,0,sizeof(dp));
          for(int i = 1; i <= N; i++)
          {
                for(int j = M ; j >= weight[i] ; j--)
                {
                      dp[j] = max(dp[j], dp[j-weight[i]] + value[i]);
                }
          }
          cout << dp[M] << endl;
    }
    
    int main()
    {
        while(cin >> N >> M)
        {
              for(int i = 1 ; i <= N; i++)
              {
                    cin >> weight[i] >> value[i]; 
              }
              solve();
        }
        return 0;
    }

    这个代码可以保证不会内存超限

    这个是我第一次写出dp的代码,希望以后写的越来越好

  • 相关阅读:
    centos7 & ubuntu14.02安装sublime 3
    flask之flask-restful
    ubuntu14.04安装python3.7.1
    vim中多行注释和多行删除命令
    python3之scrapy安装使用
    python3 之 linux命令实现
    ubuntu14.04安装pyspider
    升级3.4成3.6 ubuntu14.04 和miniconda虚拟环境
    python3 之初学者常犯的5个错误
    python3 之 格式化json
  • 原文地址:https://www.cnblogs.com/pprp/p/7351268.html
Copyright © 2011-2022 走看看