POJ1015 DP
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 28927 | Accepted: 7676 | Special Judge |
Description
Based on the grades of the two parties, the judge selects the jury. In order to ensure a fair trial, the tendencies of the jury to favour either defence or prosecution should be as balanced as possible. The jury therefore has to be chosen in a way that is satisfactory to both parties.
We will now make this more precise: given a pool of n potential jurors and two values di (the defence's value) and pi (the prosecution's value) for each potential juror i, you are to select a jury of m persons. If J is a subset of {1,..., n} with m elements, then D(J ) = sum(dk) k belong to J
and P(J) = sum(pk) k belong to J are the total values of this jury for defence and prosecution.
For an optimal jury J , the value |D(J) - P(J)| must be minimal. If there are several jurys with minimal |D(J) - P(J)|, one which maximizes D(J) + P(J) should be selected since the jury should be as ideal as possible for both parties.
You are to write a program that implements this jury selection process and chooses an optimal jury given a set of candidates.
Input
These values will satisfy 1<=n<=200, 1<=m<=20 and of course m<=n. The following n lines contain the two integers pi and di for i = 1,...,n. A blank line separates each round from the next.
The file ends with a round that has n = m = 0.
Output
On the next line print the values D(J ) and P (J ) of your jury as shown below and on another line print the numbers of the m chosen candidates in ascending order. Output a blank before each individual candidate number.
Output an empty line after each test case.
Sample Input
4 2
1 2
2 3
4 1
6 2
0 0
Sample Output
Jury #1
Best jury has value 6 for prosecution and value 4 for defence:
2 3
Hint
Source
/*
为叙述问题方便,现将任一选择方案中,辩方总分和控方总分之差简称为“辩控差”,
辩方总分和控方总分之和称为“辩控和”。第i 个候选人的辩方总分和控方总分之差
记为V(i),辩方总分和控方总分之和记为S(i)。现用dp(j, k)表示,取j 个候选人,
使其辩控差为k 的所有方案中,辩控和最大的那个方案(该方案称为“方案dp(j, k)”)
的辩控和。并且,我们还规定,如果没法选j 个人,使其辩控差为k,那么dp(j, k)的
值就为-1,也称方案dp(j, k)不可行。本题是要求选出m 个人,那么,如果对k 的
所有可能的取值,求出了所有的dp(m, k) (-20×m≤ k ≤ 20×m),那么陪审团方案自然
就很容易找到了。
问题的关键是建立递推关系。需要从哪些已知条件出发,才能求出dp(j, k)呢?
显然,方案dp(j, k)是由某个可行的方案dp(j-1, x)( -20×m ≤ x ≤ 20×m)演化而来的。
可行方案dp(j-1, x)能演化成方案dp(j, k)的必要条件是:存在某个候选人i,i
在方案dp(j-1, x)中没有被选上,且x+V(i) = k。在所有满足该必要条件的dp(j-1, x)中
,选出 dp(j-1, x) + S(i) 的值最大的那个,那么方案dp(j-1, x)再加上候选人i,就
演变成了方案 dp(j, k)。这中间需要将一个方案都选了哪些人都记录下来。不妨将方案
dp(j, k)中最后选的那个候选人的编号,记在二维数组的元素path[j][k]中。那么方案
dp(j, k)的倒数第二个人选的编号,就是path[j-1][k-V[path[j][k]]]。假定最后算出
了解方案的辩控差是k,那么从path[m][k]出发,就能顺藤摸瓜一步步回溯求出所有被选中的候选人。
初始条件,只能确定dp(0, 0) = 0,其他均为-1。由此出发,一步步自底向上递推,就
能求出所有的可行方案dp(m, k)( -20×m ≤ k ≤ 20×m)。实际解题的时候,会用一个二维
数组dp 来存放dp(j, k)的值。而且,由于题目中辩控差的值k 可以为负数,而程序中数
租下标不能为负数,所以,在程序中不妨将辩控差的值都加上修正值fix=400,以免下标
为负数导致出错。
为什么fix=400?这是很显然的,m上限为20人,当20人的d均为0,p均为20时,会出现辨
控差为-400。修正后回避下标负数问题,区间整体平移,从[-400,400]映射到[0,800]。
此时初始条件修正为dp(0, fix) = 0,其他均为-1。
DP后,从第m行的dp(m, fix)开始往两边搜索最小|D-P| 即可,第一个不为dp[m][k]!=-1的
位置k就是最小|D-P|的所在。
最后就是求m个人的D和P,由于D+P = dp(m, |D-P| ) ,|D-P|已知。
那么D= (D+P + |D-P| )/2 , P=(D+P-|D-P| ) / 2
计算D和P时注意修正值fix
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int d[],p[],c[],h[],f[][],path[][];
int main()
{
int n,m,cas=;
while(scanf("%d%d",&n,&m)&&(n+m)){
for(int i=;i<=n;i++){
scanf("%d%d",&d[i],&p[i]);
c[i]=d[i]-p[i];
h[i]=d[i]+p[i];
}
memset(f,-,sizeof(f));
memset(path,,sizeof(path));
int M=m*;
f[][M]=;
for(int i=;i<m;i++){
for(int j=;j<=M*;j++){
if(f[i][j]==-) continue;
for(int k=;k<=n;k++){
if(f[i][j]+h[k]>f[i+][j+c[k]]){
int t1=i,t2=j;
while(t1>&&path[t1][t2]!=k){
t2-=c[path[t1][t2]];
t1--;
}
if(t1==){
f[i+][j+c[k]]=f[i][j]+h[k];
path[i+][j+c[k]]=k;
}
}
}
}
}
int i;
for(i=;;i++){
if(f[m][M+i]!=-) break;
if(f[m][M-i]!=-) break;
}
int ans1,ans2,t1=m,t2;
if(f[m][M+i]>f[m][M-i]){
ans1=(i+f[m][M+i])/;
ans2=f[m][M+i]-ans1;
t2=M+i;
}
else{
ans1=(-i+f[m][M-i])/;
ans2=f[m][M-i]-ans1;
t2=M-i;
}
printf("Jury #%d\n",++cas);
printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
int tmp[],cnt=;
while(t1){
tmp[cnt++]=path[t1][t2];
t2-=c[path[t1][t2]];
t1--;
}
sort(tmp,tmp+cnt);
for(int j=;j<cnt;j++) printf(" %d",tmp[j]);
printf("\n\n");
}
return ;
}
POJ1015 DP的更多相关文章
- POJ1015 && UVA - 323 ~Jury Compromise(dp路径)
In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting of ...
- poj1015 正解--二维DP(完全背包)
题目链接:http://poj.org/problem?id=1015 错误解法: 网上很多解法是错误的,用dp[i][j]表示选择i个人差值为j的最优解,用path[i][j]存储路径,循环次序为“ ...
- poj1015陪审团——DP+路径记录
题目:http://poj.org/problem?id=1015 DP的第一维是选了几个人,第二维是当前D与P的差值,而值存的是当前D与P的和: 技巧1:通过平移避免负角标,即代码中的fix: 技巧 ...
- poj1015【DP.......无奈了】
首先,读题,真是一窍不通.后来看完程序的意思,才明白吧.. 题意: n个人中选m个,条件是取sum|D-P|最小,当有|D-P|相同的时候取|D+P|最大的.然后输出那些m个人的sumD,sumP,最 ...
- $POJ1015\ Jury\ Compromise\ Dp$/背包
洛谷传送门 $Sol$ 这是一道具有多个“体积维度”的$0/1$背包问题. 把$N$个候选人看做$N$个物品,那么每个物品有如下三种体积: 1.“人数”,每个候选人的“人数”都是$1$,最终要填满容积 ...
- POJ-1015 Jury Compromise(dp|01背包)
题目: In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting ...
- POJ1015陪审团(Jury Compromise)——dp+路径记录
题目:http://poj.org/problem?id=1015 差值是有后效性的,所以“转化为可行性”,开一维记录“能否达到这个差值”. 当然可以开两维分别记录 a 和 b,但 “值只是0或1” ...
- 【poj1015】 Jury Compromise
http://poj.org/problem?id=1015 (题目链接) 题意 随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m 人组成陪审团.选m人的办法是:控方和辩方会根据对候选人的喜欢 ...
- DP总结 ——QPH
常见优化 单调队列 形式 dp[i]=min{f(k)} dp[i]=max{f(k)} 要求 f(k)是关于k的函数 k的范围和i有关 转移方法 维护一个单调递增(减)的队列,可以在两头弹出元素,一 ...
随机推荐
- Icingaweb2监控oracle数据库的安装配置流程
Icinga2安装配置check_oracle_health流程 1.安装 由于check_oracle_health是使用perl语言编写的,因此在安装该插件之前,首先要安装oracle的客户端实例 ...
- 软件工程第四周作业-PSP
psp表格 类别 内容 开始时间 结束时间 中断时间 delta时间 学习 学习C# 10.6下午7:00 10.6下午8:00 - 60min 写代码 写主函数以及一些小的方法 10.7下午2:00 ...
- “Hello world!”团队第二周贡献分规则+贡献分数分配结果
一.贡献规则制定: (1)基础分:9 , 9 , 8 , 7 , 7 , 7 , 6(按在本次编程中承担模块的重要度制定,某一模块重要度的认定通过组内开会讨论决定) (2)会议分:每人没出勤一次会议记 ...
- Daily Scrum 9
今天我们的开会内容有一下部分: Part 1:讨论当前遇到的困难 Part 2:明天的任务分工 ◆Part 1 当前的困难 由于之前我们得到的学长的文件并不完整,导致我们无法打开,在和老师进行积极沟通 ...
- from module import 和 import 的区别
最近在用codecademy学python,遇到一些题目错误,小小记录一下 如from math import sqrt是把sqrt作为本文件的方法导入进来了,使用的时候只需要直接调用sqrt. 而如 ...
- .getClass()和.class的区别
一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到java的反射----- Java反射学习 所谓反射,可以 ...
- TCP/IP 三次握手四次挥手
TCP运输连接 TCP连接建立过程中要解决以下三个问题: (1)要使每一方能够确知双方的存在. (2)要允许双方协商一些参数(如最大窗口值.是否使用窗口扩大选项和时间戳选项以及服务质量等). (3)能 ...
- SERVER 2008 R2 SP1下的内存虚拟盘(支持32位,64位的所有windows版本)
一时冲动把笔记本的系统换成了2008 R2 SP1的,本来想着用笔记本开HYPER-V的,结果是失败了,我发现我的4750G开了HYPER-V后CPU一直居高不下,其中有个什么系统软件保护的服务就占用 ...
- 面试中常用排序算法的python实现和性能分析
这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...
- 在Ubuntu系统下编译arcsim仿真器
首先,用tar zxvf arcsim-0.2.1.tar.gz 将软件包解压 然后,打开里面的INSTALL文件,按照里面的步骤一步一步安装库.Ubuntu13.04下 1.BLAS sudo ap ...