zoukankan      html  css  js  c++  java
  • Jury Compromise

    Jury Compromise

    有n对数,每对数由((d_i,p_i))组成,现在要求选出m对数,(sum)表示对这m对数中的元素累加,在(|sum d_i-sum p_i|)最小的前提下,保证(sum d_i+sum p_i)最大,,输出(sum d_i,sum p_i),(1<=n<=200, 1<=m<=20,d_ileq 20,p_ileq 20)

    对于绝对值问题,常采取去绝对值的方法,如波浪,就是采取递增填排列,忽略了绝对值的影响,或者是直接可以进行转移,如making grade。

    此处肯定要以处理到哪一对数为阶段,两个阶段之间存在影响,故无法去绝对值,但是注意到数据范围很小,于是a我们可以直接转移绝对值,于是不难想到(f[i][j][k])表示考虑到第i对数,已经选了j对数,(sum d_i-sum p_i)为k的最大的(sum d_i+sum p_i),于是不难有转移

    [f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k-(d_i-p_i)]+d_i+p_i) ]

    边界:(f[0][0][0]=0),其余负无限大

    答案:(f[n][m][d]),(|d|)尽可能小

    而且注意到第一维可以丢掉,类似背包,再进行倒序枚举即可。

    参考代码:

    未压维

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    using namespace std;
    int dp[201][21][901],pre[201][21][901],
        d[201],p[201];
    template<class free>
    il free Max(free,free);
    il void print(int,int,int);
    int main(){
        int n,m,tot(0);
        while(scanf("%d%d",&n,&m),n,m){
            for(ri int i(1);i<=n;++i)
                scanf("%d%d",&d[i],&p[i]);
            memset(dp,-127,sizeof(dp)),memset(pre,0,sizeof(pre));
            dp[0][0][450]=0;
            for(ri int i(1),j,k;i<=n;++i){
                for(k=0;k<=900;++k)dp[i][0][k]=dp[i-1][0][k];
                for(j=1;j<=m;++j)
                    for(k=0;k<=900;++k)
                        if(k-(d[i]-p[i])>=0&&k-(d[i]-p[i])<=900){
                            dp[i][j][k]=dp[i-1][j][k];
                            if(dp[i-1][j-1][k-(d[i]-p[i])]+d[i]+p[i]>dp[i][j][k])
                                dp[i][j][k]=dp[i-1][j-1][k-(d[i]-p[i])]+d[i]+p[i],pre[i][j][k]=1;
                        }
            }int ans(0);
            for(ri int i(450);i<=900;++i)
                if(dp[n][m][i]>=0||dp[n][m][900-i]>=0){
                    if(dp[n][m][i]>dp[n][m][900-i])ans=i;
                    else ans=900-i;
                    break;
                }
            printf("Jury #%d
    Best jury has value %d for prosecution and value %d for defence:
    ",
                   ++tot,dp[n][m][ans]+ans-450>>1,dp[n][m][ans]-(dp[n][m][ans]+ans-450>>1));
            print(n,m,ans),putchar('
    '),putchar('
    ');
        }
        return 0;
    }
    il void print(int a,int b,int c){
        if(!a||!b||!c)return;
        if(pre[a][b][c]){
            print(a-1,b-1,c-(d[a]-p[a]));
            printf("%d ",a);
        }
        else print(a-1,b,c);
    }
    template<class free>
    il free Max(free a,free b){
        return a>b?a:b;
    }
    

    压了维

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    using namespace std;
    bool pre[201][21][901];
    int d[201],p[201],dp[21][901];
    void print(int,int,int);
    int main(){
        int n,m,i,j,k,tot(0);
        while(scanf("%d%d",&n,&m),n&&m){
            memset(pre,0,sizeof(pre));
            memset(dp,-127,sizeof(dp));
            dp[0][450]=0;
            for(i=1;i<=n;++i){
                scanf("%d%d",&d[i],&p[i]);
                for(j=m;j;--j)
                    for(k=0;k<=900;++k){
                        if(k-(d[i]-p[i])<0||k-(d[i]-p[i])>900)continue;
                        if(dp[j-1][k-(d[i]-p[i])]+d[i]+p[i]>dp[j][k])
                            dp[j][k]=dp[j-1][k-(d[i]-p[i])]+d[i]+p[i],pre[i][j][k]|=true;
                    }
            }
            for(j=450;j<=900;++j)
                if(dp[m][j]>=0||dp[m][900-j]>=0){
                    if(dp[m][j]>dp[m][900-j])i=j;
                    else i=900-j;
                    break;
                }j=dp[m][i]+i-450>>1,k=dp[m][i]-j;
            printf("Jury #%d
    Best jury has value %d for prosec"
                   "ution and value %d for defence:
    ",++tot,j,k),
                print(n,m,i),putchar('
    '),putchar('
    ');
        }
        return 0;
    }
    void print(int a,int b,int c){
        if(!a||!b)return;
        if(pre[a][b][c])
            print(a-1,b-1,c-(d[a]-p[a])),
                printf(" %d",a);
        else print(a-1,b,c);
    }
    
    
  • 相关阅读:
    [转]Connecting To SQLite Database Using Node.js
    [转]Ubuntu安装ss客户端
    ubuntu18.04连接pptpd服务器(未成功)
    ubuntu18.04安装DB2 11.1 Express-c
    ubuntu 18.04使用sysbench测试MySQL性能
    ubuntu18.04手动安装二进制MySQL8.0
    ubuntu 18.04下载mysql8.0.13源码并编译安装(暂时没有成功)
    Linux使用sleep进行延迟实验
    『浅入浅出』MySQL 和 InnoDB
    『浅入深出』MySQL 中事务的实现
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10917485.html
Copyright © 2011-2022 走看看