• 背包问题找物品


    艾迪是参加ACM ICPC比赛的选手。ACM是算法、编码和数学的简称。因为在ACM比赛中,最重要的知识是算法,其次是编码(实现能力),然后是数学。然而,在2018年ACM ICPC世界总决赛上,艾迪没能解出一个物理方程,这让他失去了一枚可能的奖牌。
    从那时起,艾迪发现物理学实际上是竞赛中最重要的东西。因此,他想组建一个团队来指导接下来的选手去征服PACM比赛(PACM是物理、算法、编码、数学的简称)。
    有N个候选组,每个组由pi物理专家、ai算法专家、ci编码专家、mi数学专家组成。对于每一组,艾迪可以邀请所有的人,也可以不邀请他们。如果i-th团队被邀请,他们将带来gi知识点,这是由Eddy的神奇公式计算出来的。艾迪认为,一个团队的总知识点越高,就越能在比赛中占据优势。但是,艾迪不希望邀请的团体中有太多在同一领域的专家。因此,邀请物理专家的数量不应超过P,算法专家A,编码专家C,数学专家M。
    艾迪仍在忙于学习物理学。你来帮助他弄清楚应该邀请哪些组,这样他们就不会超出限制,并将带来最多的知识点。

    这个是多维的01背包代码

    #include<bits/stdc++.h>
    #define MAX 40
    using namespace std;
    int dp[MAX][MAX][MAX][MAX];
    bool book[MAX][MAX][MAX][MAX][MAX];
    int a[MAX],b[MAX],c[MAX],d[MAX],v[MAX];
    int ans[MAX];
    int A,B,C,D;
    int main(void){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d %d %d %d %d",&a[i],&b[i],&c[i],&d[i],&v[i]);
        }
        scanf("%d %d %d %d",&A,&B,&C,&D);
        for(int i=0;i<n;i++)
            for(int k1=A;k1>=a[i];k1--)
                for(int k2=B;k2>=b[i];k2--)
                   for(int k3=C;k3>=c[i];k3--)
                     for(int k4=D;k4>=d[i];k4--)
            {
                if(dp[k1-a[i]][k2-b[i]][k3-c[i]][k4-d[i]]+v[i]>dp[k1][k2][k3][k4])
                {
                    dp[k1][k2][k3][k4]=dp[k1-a[i]][k2-b[i]][k3-c[i]][k4-d[i]]+v[i];
                book[i][k1][k2][k3][k4]=1;
                }
            }
        int k=0;
        for(int i=n-1;i>-1;i--){
            if(book[i][A][B][C][D])
            {
                ans[++k]=i;
                A-=a[i];
                B-=b[i];
                C-=c[i];
                D-=d[i];
            }
        }
        printf("%d
    ",k);
        for(int i=k;i>0;i--)
            printf("%d
    ",ans[i]);
    }
    这个是多重背包

    #include<bits/stdc++.h> #define MAX 1000005 #define INF 0x3f3f3f3f using namespace std; int dp[MAX]; int sing[MAX]; int main(void){ int n; memset(sing,-1,sizeof(sing)); scanf("%d",&n); int minm=INF; int a[10]; int it=-1; for(int i=1;i<=9;i++){ scanf("%d",&a[i]); if(a[i]<minm) minm=a[i]; } if(n<minm){ printf("-1 "); return 0; } for(int i=9;i>=1;i--) for(int j=a[i];j<=n;j++){ int temp=dp[j-a[i]]+1; if(temp>dp[j]){ dp[j]=temp; sing[j]=i;//记录物品; } } int j=n; map<int,int>mp; while(sing[j]!=-1){//遍历物品。 mp[sing[j]]++; j-=a[sing[j]]; } for(int i=9;i>=1;i--){ if(mp[i]!=0){ for(int j=0;j<mp[i];j++){ printf("%d",i); } } } return 0; }
  • 相关阅读:
    关于View的onMeasure()、onSizeChanged()、onLayout()、onDraw()调用顺序
    Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
    Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
    自定义View经常重写的方法
    为自己的自定义View添加额外属性
    自定义View常用的获取宽高信息
    用工厂流水线的方式来理解 RxJava 的概念
    发布开源项目到Maven 中心仓库
    Android应用架构之Retrofit使用
    docker新手入门(基本命令以及介绍)
  • 原文地址:https://www.cnblogs.com/linhaitai/p/9190153.html
Copyright © 2020-2023  润新知