zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x52背包DP 陪审团(背包DP扩展)

    题目链接:https://www.acwing.com/problem/content/description/282/

    题目给出两个序列p,d 要求寻找一个方案,使得p-d的绝对值最小,在绝对值相同的情况下p+d的值尽量大,通过dp保存状态:前i个人中选择了j个,并且差为k时的p+d的最大值。转移方式就是划分集合,判断是否选择第i个人,最后通过回溯即可判断是否选择一个人。这里的差值在[-400,400]之间,所以可以加上偏移400使得下标为正。最初的状态只有f[0,0,400]=0,表示没开始选择的时候,差值为0的最大值为0。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 210,maxm = 810,base=400;
    int n,m;
    int p[maxn],d[maxn];
    int f[maxn][21][maxm];
    int ans[maxn];
    int main(){
        int T=1;
        while(scanf("%d%d",&n,&m),n||m){
            for(int i=1;i<=n;i++)scanf("%d%d",&p[i],&d[i]);
            
            memset(f,-0x3f,sizeof f);
            f[0][0][base]=0;//起初只有一个合法状态
            
            for(int i=1;i<=n;i++)
                for(int j=0;j<=m;j++)
                    for(int k=0;k<maxm;k++){
                        f[i][j][k]=f[i-1][j][k];
                        int t=k-(p[i]-d[i]);
                        if(t<0 || t>=maxm)continue;
                        if(j<1)continue;
                        f[i][j][k]=max(f[i][j][k],f[i-1][j-1][t]+p[i]+d[i]);
                }
                
            int v=0;//判断差值最小的方案 
            while(f[n][m][base-v]<0 && f[n][m][base+v]<0)v++;
            
            if(f[n][m][base-v]>f[n][m][base+v])v=base-v;
            else v=base+v;
            
            int cnt = 0;
            int i=n,j=m,k=v;
            while(j){//状态回溯 
                if(f[i][j][k]==f[i-1][j][k])i--;
                else{
                    ans[cnt++]=i;
                    k-=(p[i]-d[i]);
                    i--,j--;
                }
            }
            
            int sp=0,sd=0;
            for(int i=0;i<cnt;i++)
                sp+=p[ans[i]],sd+=d[ans[i]];
            printf("Jury #%d
    ",T++);
            printf("Best jury has value %d for prosecution and value %d for defence:
    ",sp,sd);
            for(int i=0;i<cnt;i++)printf(" %d",ans[i]);
            cout<<endl<<endl;
        }
        return 0;
    }
  • 相关阅读:
    国产开源软件
    Tomcat系统架构
    移动端前端常见的触摸相关事件touch、tap、swipe
    spring配置文件详解
    Java获取文件中视频的时长
    java命令行导出、导入sql文件
    Java国密相关算法(bouncycastle)
    Java中将对象转换为Map的方法
    Virtual Box虚拟机下CentOS网络设置
    VirtualBox安装虚拟机全过程
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13402053.html
Copyright © 2011-2022 走看看