poj-1015&&UVA-323 Jury Compromise正解

2 篇文章 0 订阅

网络上大部分关于poj1015的题解都是假的,原因是poj的数据比较水。

比如以下数据能hack大部分题解

9 6 
6 2 
16 10 
4 9 
19 8 
17 12 
4 7 
10 2 
2 14 
5 18 
0 0

正解应该是

Jury #1
Best jury has value 54 for prosecution and value 54 for defence:
 1 2 3 4 6 9

uva的数据是加强过的,poj的时限和内存卡的更难受一点

所以同时过了uva和poj才能说过了这道题(或者只是uva

题目链接

题解:就是把每个可能的终点都找出来的时候,把相应终点的使权值最大的路径全部记录(详情请看代码

这份是我的uva的ac代码,提交到poj上需要把auto改掉而且把maxn,maxm卡的更小一点才不会CE和MLE

#include<stdio.h>
#include<cstring>
typedef long long ll;
using namespace std;

const int maxm = 25;
const int maxn = 205;
const int zero = 25;
const int VAL = 45;

struct node{
	int val,sum;
	//sum为每个人的权值,val为每个人对被告和原告的好感差
}d[maxn];

struct res{
	int x,id,k;//k表示这个答案是否存在,x表示当前答案的权值和,id表示从上一层更新到这一层这个答案所使用的id
	res *Next;//记录每个每个可能答案的路径
}dp[maxn][maxm][maxm*VAL+1],*ans;

void output(res *p) {
	if(p){//初始化后dp[0][0][0].Next=0;
		output(p->Next);
		if(p->id) {
			printf(" %d", p->id);
		}
	}
}
int n,m,sum,tt=0,x,y,ans_val;

int main() {
    //freopen("123.in","r",stdin);
    while(~scanf("%d%d",&n,&m)&&n){
        tt++;
        for(int i=1;i<=n;++i){
            scanf("%d%d",&x,&y);
            d[i].val=x-y+zero;//把负号去掉
            d[i].sum=x+y;
        }
        memset(dp,0,sizeof dp);
        dp[0][0][0].k=1;
        for(int i=1;i<=n;++i){
            dp[i][0][0].k=1;//对于每个人都可能是从0开始的第一个陪审团成员
            for(int j=1;j<=m;++j){
                int mx=j*VAL,pos=d[i].val;
                for(int k=0;k<=mx;++k){
                    dp[i][j][k]=dp[i-1][j][k];//把第i-1个人的状态递推到最后一个
                    if(k<pos)continue;
                    res &tmp=dp[i-1][j-1][k-pos],&now=dp[i][j][k];
                    if(tmp.k&&tmp.x+d[i].sum>=now.x){//是否存在更优解
                        now.x=tmp.x+d[i].sum;
                        now.Next=&tmp;//保存父节点记录路径
                        now.id=i;
                        now.k=1;
                    }
                }
            }
        }
        int mid=m*zero;
        sum=-1;
        auto ch=dp[n][m];
        for(int i=0;i<=mid;i++){
            int l=mid-i,r=mid+i;
            if(ch[l].k||ch[r].k){//先保证最接近,然后保证权值和最大
                ans_val=(ch[l].x>ch[r].x?-i:i);
                sum=(ch[l].x>ch[r].x?ch[l].x:ch[r].x);
                ans=(ch[l].x>ch[r].x?&ch[l]:&ch[r]);
            }
            if(~sum)break;
        }
        x=(ans_val+sum)/2,y=sum-x;
        printf("Jury #%d\nBest jury has value %d for prosecution and value %d for defence:\n",tt,x,y);
        output(ans);
		puts("\n");
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值