zoukankan      html  css  js  c++  java
  • 普通背包水题集合 2019/6/17

    最近没写DP,回来写几道水题。

    P1064 金明的预算方案

    有连带条件的背包问题,对于每个非叶子节点,他的每一个儿子的组合方式都可以枚举跑,类似于树形DP但简单的多

    对于每个父亲,选择1号儿子,选择2号儿子,12儿子都选,都不选,或者是自己都不选(写转移时体现在MAX)

    注意下标越界和末状态,以及代码构造技巧。

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,mw[65],mc[65],aw[65][5] ,ac[65][5],f[50000];
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            int v,p,q;
            cin>>v>>p>>q;
            if(!q){
                mw[i] = v;
                mc[i] = v * p;
            }
            else {
                aw[q][0] ++;
                aw[q][aw[q][0]] = v;
                ac[q][aw[q][0]] = v * p;
            }
        }
        for(int i=1;i<=m;i++){
            for(int j=n;mw[i] != 0 && j >= mw[i];j--){//倒序 01背包 
                f[j]  = max(f[j] , f[j - mw[i]] + mc[i]);
                if(j >= mw[i] + aw[i][1])
                    f[j] = max(f[j],f[j-mw[i]-aw[i][1]] + mc[i] + ac[i][1]);
                if(j >= mw[i] + aw[i][2])
                    f[j] = max(f[j],f[j-mw[i]-aw[i][2]] + mc[i] + ac[i][2]);
                if(j >= mw[i] + aw[i][1] + aw[i][2])
                    f[j] = max(f[j],f[j-mw[i]-aw[i][1]-aw[i][2]] + mc[i] + ac[i][1] + ac[i][2]);
            }
        }
        cout<<f[n]<<endl;
        return 0;
    }

    P1049 装箱问题

    我傻了,刚看到时还以为是什么恰好背包,谢罪谢罪.......

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 35,MAXM = 20010;
    int n,a[MAXN],f[MAXM],m;
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            cin>>a[i];
        }
        for(int i = 1;i<=m;i++){
            int nv = a[i];
            for(int j = n;j>=nv;j--){
                f[j] = max(f[j] , f[j-nv] + nv);
            }
        }
        cout<<n-f[n]<<endl;
        return 0;
    }

    P1455 搭配购买

    我也想买云朵...(你写的题怎么都这么水啊)

    并查集,合并物品,背包,perfect。

    等等让我去看看并查集怎么写(打死自己)

    #include<bits/stdc++.h>
    
    using namespace std; 
    
    const int MAXN = 10100;//第一次数组还开小了
    struct RAINBOW{
        int cos,val;
    }a[MAXN],b[MAXN];
    
    int n,m,v,fa[MAXN],f[MAXN];
    int find(int x){
        return (fa[x] == x) ? x : fa[x] = find(fa[x]);
    }
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m>>v;
        for(int i=1;i<=n;i++){
            cin>>a[i].cos>>a[i].val;
        }
        for(int i=1;i<=n;i++) fa[i] = i;
        for(int i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
    //蒟蒻自裁 这里并查集写错导致WA了一次
    if(find(x) != find(y)) fa[find(x)] = y;//是合并他们的父亲 不是儿子简单连边 } for(int i=1;i<=n;i++){ int now = find(i); b[now].cos += a[i].cos; b[now].val += a[i].val; } for(int i=1;i<=n;i++){ if(b[i].val){ for(int j=v;j>=b[i].cos;j--){ f[j] = max(f[j],f[j-b[i].cos] + b[i].val); } } } cout<<f[v]<<endl; return 0; }

    P1910 L国的战斗之间谍

    第一眼:什么东西?

    然后仔细看觉得应该就是个强制压掉一位的01背包

    一看数据范围1000*1000 空间应该是对的吧

    然后就A了 注意循环时的顺序和下标爆炸问题

    但是蒟蒻跑了4000ms被爆踩

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 105,MAXM = 1010;
    struct PEOPLE{
        int val,cov,cos;
    }a[MAXN];
    
    int n,c,v;
    int f[MAXM][MAXM];
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>c>>v;
        for(int i=1;i<=n;i++){
            cin>>a[i].val>>a[i].cov>>a[i].cos;
        }
        for(int i=1;i<=n;i++){
            for(int k=c;k>=a[i].cov;k--){
                for(int l=v;l>=a[i].cos;l--){
                    f[k][l] = max(f[k][l],f[k-a[i].cov][l-a[i].cos] + a[i].val);
                }
            }
        }
        cout<<f[c][v]<<endl;
        return 0;
    }

    P1510 精卫填海

    水题,直接跑压掉第几个石头的01背包

    最后遍历最后一行统计答案

    #include<bits/stdc++.h>
    
    using namespace std ;
    
    const int MAXN = 10010;
    int v,n,c;
    struct STONE{
        int v,cos;
    }a[MAXN];
    
    int f[MAXN];//tag->cos f[]->v
    
    int main(){
        ios::sync_with_stdio(false);
        cin>>v>>n>>c;
        for(int i=1;i<=n;i++) {
            cin>>a[i].v>>a[i].cos;
        }
        for(int i=1;i<=n;i++) {
            for(int j=c;j>=a[i].cos;j--){
                f[j] = max(f[j],f[j-a[i].cos] + a[i].v);
            }
        }
        int ans = -1;
        for(int i=1;i<=c;i++){
            if(f[i] >= v) ans = max(ans,c-i);
        }
        if(ans == -1){
            cout<<"Impossible"<<endl;
            return 0;
        }
        cout<<ans<<endl;
        return 0;
    }

    持续更新

    TAG:SIN_XIII ⑨

  • 相关阅读:
    sqlServer的主键只能自增不能手动增加
    TP函数
    TP复习17
    TP复习16
    TP复习15
    TP复习14
    TP复习13
    TP复习12
    TP复习11
    TP复习10
  • 原文地址:https://www.cnblogs.com/SINXIII/p/11041156.html
Copyright © 2011-2022 走看看