poj 1015 Jury Compromise_dp

题意:n个陪审团,每个陪审团有x,y值,选出m个陪审团,要求 (sum(xi)-sum(yi))最少,当 (sum(xi)-sum(yi))最少有多个,取sum(xi)+sum(yi)最大那个

,并顺序输出陪审团的序号

思路:先x-y,x+y存起来,再按当dp[i][j],j相同时,要值最大,当然存路径是最烦的。

#include <iostream>
#include<cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
#define N 210
int path[25][1000],map[25][1000],n,m,sub[25*10],plusa[25*10],size,ans[25];
int main(int argc, char** argv) {
	int i,j,k,x,y,cas=1;
	while(scanf("%d%d",&n,&m)!=EOF,n||m){
		for(i=1;i<=n;i++){
			scanf("%d%d",&x,&y);
			sub[i]=x-y;
			plusa[i]=x+y;		
		}
		memset(map,-1,sizeof(map));
		memset(path,-1,sizeof(path));
		size=25*m;
		map[0][size]=0;
		path[0][size]=0;
		for(i=1;i<=n;i++){
			if(map[1][size+sub[i]]<plusa[i]){
				map[1][size+sub[i]]=plusa[i];
				path[1][size+sub[i]]=i;
			}
		}
		for(i=1;i<m;i++){
			for(j=0;j<2*size;j++)
				if(path[i][j]>=0){
					for(k=1;k<=n;k++){
						if(map[i+1][j+sub[k]]<map[i][j]+plusa[k]){
							for(x=i,y=j;x>=1;x--){
								if(path[x][y]==k)
									break;
								y-=sub[path[x][y]];
							}
							if(x<1){
								map[i+1][j+sub[k]]=map[i][j]+plusa[k];
								path[i+1][j+sub[k]]=k;
							}
						}
					}
				}
		}
		int num=0;
		for(i=0;i<=2*size;i++){
			if(map[m][size+i]>=0||map[m][size-i]>=0){
				if(map[m][size+i]>map[m][size-i])
					j=size+i;
				else
					j=size-i;
				break;
				
			}
		}
		for(i=m,k=j;i>=1;i--){
			ans[num++]=path[i][k];
			k-=sub[ans[num-1]];
		}
		sort(ans,ans+num);
		printf("Jury #%d\n",cas++);
		printf("Best jury has value %d for prosecution and value %d for defence: \n",(map[m][j]+j-size)/2,(map[m][j]-(j-size))/2);
		for(i=0;i<num;i++){
			printf(" %d",ans[i]);
		}
		printf("\n");
	}
	return 0;
}


posted @ 2014-03-10 21:43  Teemo的技术blog  阅读(108)  评论(0编辑  收藏  举报