POJ 1015 Jury Compromise

题意:从n个陪审员中选出m个,每个陪审员有控诉和辩护两个属性,要求两个属性和的差值最小,在这种情况下,总值最大(为了保证法庭的精彩??)。

dp[i][j]表示选到第i个陪审员的时候,差值为[j]时,最大的总值。用path[i][j]记录选择了哪个。

注意pos与i的关系。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#define N 1000
#define ll long long
#define INF 0x7fffffff
#define MST(x) memset(x,0,sizeof(x))
using namespace std;
struct Node{
    int x,y,z;
    Node(int a = 0,int b = 0){
        x = a,y = b,z = a - b;
    }
};

Node l[N];

int path[210][9000];
bool select(int i,int j,int k){//检测path[i][j]里有没有k
    while (path[i][j] != k && path[i][j] != 0)
    {
        j-=l[path[i][j]].z;
        i--;
    }
    if(path[i][j] == k){
        return 0;
    }
    return 1;
}

int n,m;
int fix;
int dp[210][9000];

int main(){
    int i,j,k;
    int x,y;
    int time = 1;
    while(scanf("%d%d",&n,&m),n||m){
        fix = 20 * m;
        for(i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            l[i] = Node(x,y);
        }
        memset(dp,-1,sizeof(dp));
        memset(path,0,sizeof(path));
        dp[0][fix] = 0;
        for(i=1;i<=m;i++){
            for(j=0;j<=fix*2;j++){
                if(dp[i-1][j] != -1){//j有东西
                    for(k=1;k<=n;k++){
                        if(select(i-1,j,k) && dp[i][j + l[k].z] < dp[i-1][j] + l[k].x + l[k].y){
                            dp[i][j + l[k].z] = dp[i-1][j] + l[k].x + l[k].y;
                            path[i][j + l[k].z] = k;
                        }
                    }
                }
            }
        }
        int ans = 0;
        int cha;
        for(i=0;i<=fix;i++){
            if(dp[m][fix - i] != -1 || dp[m][fix+i] != -1){
                ans = max(dp[m][fix - i],dp[m][fix+i]);
                cha = dp[m][fix - i] > dp[m][fix + i] ? fix-i : fix + i;
                break;
            }
        }
        printf("Jury #%d\n",time++);
        printf("Best jury has value %d for prosecution and value %d for defence: \n",(ans+cha - fix)/2,(ans-cha + fix)/2);
        ans = path[m][cha];//cha是差值
        int arr[300];
        int top = 0;
        while (path[m][cha] != 0)
        {
            arr[top++] = path[m][cha];
            cha -= l[path[m][cha]].z;
            m--;
        }
        sort(arr,arr + top);
        for(i=0;i<top;i++){
            printf(" %d",arr[i]);
        }
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值