• 背包问题总览(图)


    猛然心血来潮写了一黑板的背包问题总览。

    小班同志可以根据这顺序学习DP解决背包问题。

    这个脑图很清楚的写出了背包问题的基本类别和思路(思路好像上厕所去了……)

    总结和模板改天有空发上来。

    ps:微软这个扫描软件真管用……前几天扫身份证,今天扫黑板,很方便。

     

     

    简单的背包问题(洛谷试炼场->普及练习场->动态规划的背包问题):

    (一)01背包 (大部分可直接用模板解决)

      (1)洛谷【p1060】开心的金明 (标准的01背包问题)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int N,m;
    int v[300],p[300];
    int f[50001];
    int want=0;
    
    int main(){
        cin>>N>>m;
        for(int i=0;i<m;i++){
            cin>>v[i]>>p[i];
            p[i] *= v[i];
        }
        for(int i=0;i<m;i++){
            for(int j=N;j>v[i];j--){
                if(f[j-v[i]]+p[i]>f[j]){
                    f[j]=f[j-v[i]]+p[i];
                }
            }
        }
        cout<<f[N];
        return 0;
    } 
    

      (2)洛谷【p1048】采药 (标准的01背包问题)

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int T,m;
    int w[1000],c[1000],f[100000];
    
    int main()
    {
      cin>>T>>m;
      for(int i=1;i<=m;i++){
        cin>>w[i]>>c[i];
      }
      for(int i=1;i<=m;i++){
        for(int j = T;j>=w[i];j--){
          if(f[j-w[i]]+c[i]>f[j]){
            f[j]= f[j-w[i]]+c[i];
          }
        }
      }
      cout<<f[T];
    }

      (3)洛谷【p1049】装箱问题 (01背包问题,物品重量和价值相同)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int v,n;
    int c[35],f[100000];
    int main()
    {
      cin>>v>>n;
      for(int i =1;i<=n;i++){
        cin>>c[i];
      }
      for(int i =1;i<=n;i++){
        for(int j=v;j>=c[i];j--){
          if(f[j-c[i]]+c[i]>f[j]){
            f[j]=f[j-c[i]]+c[i];
          }
        }
      }
      cout<<v-f[v];
    }

    (二)背包方案计数:

      (2)洛谷【P1164】 小A点菜 (01背包解决方案计数问题)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int c[2000];
    long long int f[100000];
    int n,m;
    int main(){
      cin>>n>>m;
      for(int i=0;i<n;i++){
        cin>>c[i];
      }
      f[0]=1;
      for(int i =0;i<n;i++){
        for(int j=m;j>=c[i];j--){
          f[j]+=f[j-c[i]];
          }
        }
      cout<<f[m];
    }

    (三)依赖背包问题:

      (1)洛谷 【p1064】金明的预算方案 (树状DP)

    /*代码参考神犇博客*/
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int M = 3276;
    const int S = 80;
    vector<int> vct[S];
    vector<pair<int, int> > groups[S];
    int dp[M], n, m, w[S], v[S], d[S];
    main()
    {
        scanf("%d %d", &m, &n);
        m /= 10;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d %d %d", &w[i], &v[i], &d[i]);
            w[i] /= 10;
            v[i] *= w[i];
            if(d[i])
               vct[d[i]].push_back(i);
        }
        int cnt = 0;
        for(int i = 1; i <= n; i++)
        {
            if(d[i] == 0)
            {
                memset(dp, 0, sizeof(dp));
                dp[w[i]] = v[i];
                int sum = w[i];
                for(int j = 0; j < vct[i].size(); j++)
                {
                    int dx = vct[i][j];
                    sum += w[dx];
                    for(int k = sum; k >= w[i]; k--)
                        if(dp[k] != 0)
                            dp[k + w[dx]] = max(dp[k] + v[dx], dp[k + w[dx]]);
                }
                for(int j = w[i]; j <= sum; j++)
                    if(dp[j])
                        groups[cnt].push_back(make_pair(j, dp[j]));
                cnt++;
            }
        }
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < cnt; i++)
            for(int j = m; j >= 0; j--)
                for(vector<pair<int, int> >::iterator it = groups[i].begin(); it != groups[i].end(); it++)
                    if(j >= it ->first)
                        dp[j] = max(dp[j], dp[j - it ->first] + it ->second);
        printf("%d
    ", dp[m] * 10);
    }
    

    (四)完全背包问题:

      (1)洛谷 【p1616】疯狂的采药 (每种物品有无限数量的背包问题)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int m,n;
    int f[100010],w[10010],c[10010];
    int main(){
      cin>>m>>n;
      for(int i=1;i<=n;i++){
        cin>>w[i]>>c[i];
      }
      for(int i=1;i<=n;i++){
        for(int j = w[i];j<=m;j++){
          if(f[j-w[i]]+c[i]>f[j]) f[j] = f[j-w[i]]+c[i];
        }
      }
      cout<<f[m];
    }
    

     

     

  • 相关阅读:
    python动态网页爬取——四六级成绩批量爬取
    python&MongoDB爬取图书馆借阅记录(没有验证码)
    【Linux】CentOS 7安装与使用,安装jdk1.8,安装mysql
    JavaWeb项目:旅游网站【涉及各种知识】
    【SpringMVC】使用三层架构实现登录,注册。(下篇)
    【SpringMVC】使用三层架构实现登录,注册。(上篇)
    【JSP】el、jstl、MVC、三层架构
    【Tomcat】JSP使用Session、Cookie实现购物车
    HttpServletRequest对象,请求行、请求头、请求体
    【Spring】JdbcTemplate的使用,查询,增、删、改
  • 原文地址:https://www.cnblogs.com/zhangone/p/5574293.html
Copyright © 2020-2023  润新知