POJ 1015 Jury Compromise
2015-07-16 12:22
381 查看
题意
从n个人中选出m个,每个人有固定的p值,d值,要求使m个人的p总和和d总和的差的绝对值最小,若有多解则取两者和最大的。分析
f[i][j]表示在选m个人中的第i个人的时候使所有已选中的人的p,d差为j时,所能获得的p,d最大和。f[i + 1][j + p[k] - d[k]] = f[i][j] + p[k] + d[k];(要求k之前没有选过,要查看f[i][j]的完整路径,确保无k)
填写完成后,观察f[m]找到最小差值,最大和。知道和差自然可以求出总的p,d。
代码
一开始没有想明白,一直WA,后来看了题解才明白。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int dp[21][801],path[21][801]; int D[201],J[201],res[21]; int cmp(const void *a,const void *b){return *(int*)a-*(int*)b;} bool select(int a,int b,int i){ while(a>0 && path[a][b]!=i){ b-=D[path[a][b]]-J[path[a][b]]; a--; } return (a!=0)?true:false;//i有没有被用过。 } int main(){ int i,j,k,r,n,m,cnt=1,a,b; while(scanf("%d%d",&n,&m),n||m){ for(i=1;i<=n;i++)scanf("%d%d",&D[i],&J[i]); memset(dp,-1,sizeof(dp)); memset(path,0,sizeof(path)); r=m*20; dp[0][r]=0; for(j=0;j<m;j++) for(k=0;k<=r*2;k++) if(dp[j][k]>=0) for(i=1;i<=n;i++) if(dp[j+1][k+D[i]-J[i]]<dp[j][k]+D[i]+J[i]){//状态方程 a=j;b=k; if(!select(a,b,i)){ dp[j+1][k+D[i]-J[i]]=dp[j][k]+D[i]+J[i]; path[j+1][k+D[i]-J[i]]=i; } } for(i=r,j=0;dp[m][i+j]<0&&dp[m][i-j]<0;j++);//寻找绝对值最小的 k=dp[m][i+j]>dp[m][i-j]?i+j:i-j;//寻找绝对值最小的和最大的 printf("Jury #%d\n",cnt++); printf("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][k]+k-r)/2, (dp[m][k]-k+r)/2); for(i=1;i<=m;i++){ res[i]=path[m-i+1][k]; k-=D[res[i]]-J[res[i]]; } qsort(res+1,m,sizeof(res[0]),cmp); for(i=1;i<=m;i++)printf(" %d",res[i]); puts("\n"); } return 0; }
相关文章推荐
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)
- 【高手回避】poj3268,一道很水的dijkstra算法题
- POJ 1088 滑雪
- poj2387 Til the Cows Come Home—Dijkstra模板
- poj 2485 Highways
- poj 1511 Invitation Cards
- POJ水题1083区间重叠问题
- 【网络流-最大流-Dinic-建模】POJ3281 Dining:Pascal 解法
- poj1042
- poj1080