zoukankan      html  css  js  c++  java
  • 陪审团

    题目链接:

    https://www.acwing.com/problem/content/description/282/

    题意:

    有n个人,每个人有p,d两种属性,现在要从中选出m个人,使得p属性之和与d属性之和差的绝对值最小,若有多个方案有相同的最小绝对值差,取p+d最大的方案,并输出方案。(1≤N≤200,1≤M≤20,0≤p[i],d[i]≤20)

    思路:

    我们可以把每个人p和d的差值提高20的偏移量,这样差值就大于0了,然后01背包凑数的过程,存下每种数的p,d属性,一个数可以由多个方式凑出来时,取p+d最大的情况,最后要找到可以被凑数来且最接近m*20的数。求具体方案就倒推一遍。

    代码:

    #include<iostream>
    #include<string.h>
    #include<vector>
    #include<algorithm>
    #include<stdio.h>
    using namespace std;
    struct ac{
        int p,d,w,id;
    }a[210];
    struct de{
        int p,d,f;
    }f[210][21][810];
    vector<int> v;
    int main(){
        int n,m,cas=1;
        while(1){
            cin>>n>>m;
            if(n==0&&m==0) break;
            for(int i=1;i<=n;++i){
                cin>>a[i].p>>a[i].d;
                a[i].w=a[i].p-a[i].d+20,a[i].id=i;
            }
            int gal=m*20;
            v.clear();
            memset(f,0,sizeof f);
            f[0][0][0].f=1;f[0][0][0].p=f[0][0][0].d=0;
            for(int i=1;i<=n;++i){
                int w=a[i].w,p=a[i].p,d=a[i].d;
                memcpy(f[i],f[i-1],sizeof f[i]);
                for(int j=m;j>=1;--j){
                    for(int k=800;k>=w;--k){
                        if(f[i-1][j-1][k-w].f&&!f[i][j][k].f) {
                            f[i][j][k].f=1;
                            f[i][j][k].p=f[i-1][j-1][k-w].p+p;
                            f[i][j][k].d=f[i-1][j-1][k-w].d+d;
                        }
                        else if(f[i-1][j-1][k-w].f&&f[i][j][k].f &&f[i-1][j-1][k-w].p+f[i-1][j-1][k-w].d+p+d>f[i][j][k].p+f[i][j][k].d){
                            f[i][j][k].p=f[i-1][j-1][k-w].p+p;
                            f[i][j][k].d=f[i-1][j-1][k-w].d+d;
                        }
                    }
                }
            }
            int mn=1000000,ap=0,ad=0;
            for(int i=800;i>=0;--i) {
                if(f[n][m][i].f&&( abs(i-gal)<abs(mn-gal)||( abs(i-gal)==abs(mn-gal) && f[n][m][i].p+f[n][m][i].d>ap+ad  )   ) ){
                    mn=i;
                    ap=f[n][m][i].p;
                    ad=f[n][m][i].d;
                }
            }
             printf("Jury #%d
    ",cas++);
            printf("Best jury has value %d for prosecution and value %d for defence:
    ",ap,ad);
            int i=n,j=m;
            while((ap||ad)&&i){
                for(int k=0;k<=800;++k){
                    if(f[i-1][j-1][k].f&&ap==f[i-1][j-1][k].p+a[i].p && ad==f[i-1][j-1][k].d+a[i].d){
                        ap-=a[i].p,ad-=a[i].d;
                        v.push_back(i);
                        --j;
                        break;
                    }
                }
                --i;
            }
            reverse(v.begin(),v.end());
            for(int i=0;i<v.size();++i)  printf(" %d",v[i]);
            printf("
    
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    html集合
    pyautocad
    CAD 批量提取点坐标,实现坐标的快速提取
    CAD
    python模块
    set,get,setter
    1 Http的表皮
    (6)小项目------完善增删改查的操作
    SSM学习笔记(6)---拦截器
    SSM学习笔记(5)-CGLIB动态代理
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12691639.html
Copyright © 2011-2022 走看看