题目:

In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting of members of the general public. Every time a trial is set to begin, a jury has to be selected, which is done as follows. First, several people are drawn randomly from the public. For each person in this pool, defence and prosecution assign a grade from 0 to 20 indicating their preference for this person. 0 means total dislike, 20 on the other hand means that this person is considered ideally suited for the jury.

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:

The input file contains several jury selection rounds. Each round starts with a line containing two integers n and m. n is the number of candidates and m the number of jury members.

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:

For each round output a line containing the number of the jury selection round ('Jury #1', 'Jury #2', etc.).

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

题意:

在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是: 控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。

多组输入,每次输入n和m。1<=n<=200,1<=m<=20,m<=n。接下来n行输入的是控方和辩方对改候选人的打分,候选人编号从1开始到n。最后一组数据输入n=m=0结束。

分析:

看成从n个件物品中选取m件物品的01背包问题。用一个sum数组记录控方和辩方分数之和,de数组记录控方和辩方分数之差,并且记录当前阶段所有控方和辩方分数之和与差,这个状态可以用一个dp数组记录,此外dp数组还应记录当前已经选择的成员数,对于当前成员我们可以选择它或者不选它,如果选择它,那么控辩双方的和与差就要加上当前成员的值,并且成员数要增加一个,那么如何判断选择它还是不选它,如果选择了它能使当前控辩双方分差不变的情况下控辩双方的和变大我们就选择它,否则就跳过它,dp[i][j][k]代表当前成员编号为i,已经选择了j位成员,当前控辩双方分差为k的情况下控辩双方分差之和的最大值,由于数组的第一维可以用滚动数组省去空间,dp[i][j][k]可以转变为dp[j][k],状态转移可以表示为: if(dp[j-1][k] + sum[i] > dp[j][k+de[i]]) dp[j][k+de[i]] = dp[j-1][k] + sum[i]。代表的是如果选了第i位成员那么选择j名成员且控辩差为k+de[i]的情况能获得更优(大)解,那么就选择这位成员。但是由于k不可为负值而de数组中可能存在负值,所以可以定义20×m的点为初始点,因为每个人打分最大为20分,考虑极端情况也就是m个人的de之和会在-20×m到20×m之间,所以定义dp[0][20*m] = 0,为初始点,其他dp值全设置成-1,代表该状态没有访问过,如果一个状态的前一个状态没有访问过,那么便不需要判断状态转移方程直接continue,最后我们从20×m这个点开始向两头扩展,最先到达的已经访问过的状态便是答案(因为此时的控辩双方差是最小的并且是当前控辩双方差的所有情况中控辩双方的和最大的一个),此外还需要用一个vector定义的path数组记录路径,具体看代码操作。

代码:

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 205;
int sum[maxn],de[maxn];
int dp[25][maxn<<2];
vector<int> path[25][maxn<<2];
int main(void){
int n,m,p,d,cnt = 1;
while (scanf("%d%d",&n,&m),n+m){
for (int i = 1; i <= n; i++){
scanf("%d%d",&p,&d);
sum[i] = p+d;
de[i] = p-d;
}
int flag = m*20;
memset(dp,-1,sizeof dp);
dp[0][flag] = 0;
for (int i = 1; i <= n; i++){
for (int j = m; j >= 1; j--){
for (int k = 0; k <= flag*2; k++){
if (k+de[i] < 0 || k+de[i] > flag*2) continue;
if (dp[j-1][k] == -1) continue;
if (dp[j-1][k]+sum[i] > dp[j][k+de[i]]){
dp[j][k+de[i]] = dp[j-1][k] + sum[i];
path[j][k+de[i]] = path[j-1][k];
path[j][k+de[i]].push_back(i);
}
}
}
}
int ans = 0;
while (dp[m][flag-ans] == -1 && dp[m][flag+ans] == -1) ans++;
int tmp = dp[m][flag+ans]>dp[m][flag-ans]?flag+ans:flag-ans;
printf("Jury #%d\nBest jury has value %d for prosecution and value %d for defence:\n",cnt++,(dp[m][tmp]+tmp-flag)>>1,(dp[m][tmp]-tmp+flag)>>1);
for (int i = 0; i < m; i++){
printf(" %d",path[m][tmp][i]);
}
puts("\n");
}
return 0;
}

需要积累与学习之处:

滚动数组 path记录路径 ans = 0之后一系列操作

参考作者:

UVA 323 Jury Compromise——01背包变形

POJ-1015 Jury Compromise(dp|01背包)的更多相关文章

  1. POJ 1015 Jury Compromise dp

    大致题意: 从n个候选人中选出m个人作为陪审团.为了让陪审团的选择更公平,辩方和控方都为这n个候选人给出了满意度(辩方为D[j],控方为P[j],范围0至20).现在要使得选出的m位候选人的辩方总和与 ...

  2. POJ 1015 Jury Compromise dp分组

    第一次做dp分组的问题,百度的~~ http://poj.org/problem?id=1015 题目大意:在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑 ...

  3. 背包系列练习及总结(hud 2602 && hdu 2844 Coins && hdu 2159 && poj 1170 Shopping Offers && hdu 3092 Least common multiple && poj 1015 Jury Compromise)

    作为一个oier,以及大学acm党背包是必不可少的一部分.好久没做背包类动规了.久违地练习下-.- dd__engi的背包九讲:http://love-oriented.com/pack/ 鸣谢htt ...

  4. POJ.3624 Charm Bracelet(DP 01背包)

    POJ.3624 Charm Bracelet(DP 01背包) 题意分析 裸01背包 代码总览 #include <iostream> #include <cstdio> # ...

  5. POJ 1015 Jury Compromise(dp坑)

    提议:在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团.选m人的办法是:控方和辩方会根据对候选 ...

  6. POJ 1015 Jury Compromise(双塔dp)

    Jury Compromise Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33737   Accepted: 9109 ...

  7. poj 1015 Jury Compromise(背包+方案输出)

    \(Jury Compromise\) \(solution:\) 这道题很有意思,它的状态设得很...奇怪.但是它的数据范围实在是太暴露了.虽然当时还是想了好久好久,出题人设了几个限制(首先要两个的 ...

  8. OpenJudge 2979 陪审团的人选 / Poj 1015 Jury Compromise

    1.链接地址: http://bailian.openjudge.cn/practice/2979 http://poj.org/problem?id=1015 2.题目: 总Time Limit: ...

  9. POJ 1015 Jury Compromise (算竞进阶习题)

    01背包 我们对于这类选或者不选的模型应该先思考能否用01背包来解. 毫无疑问物体的价值可以看成最大的d+p值,那么体积呢?题目的另一个限制条件是d-p的和的绝对值最小,这启发我们把每个物体的d-p的 ...

随机推荐

  1. 如何通过模仿提升Paper写作能力?

    对于大部分初到国外留学的中国留学生们来说要想自己独立完成一篇Paper可能难度会很大,从Paper字体字号要求.Paper写作格式.Paper写作结构等等诸多因素都会影响留学生们写Paper的效率.对 ...

  2. Bean XML 配置(2)- Bean作用域与生命周期回调方法配置

    系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...

  3. python 虚拟环境的安装

    方式一 1. pip install virtualenv 2. virtualenv 虚拟环境的名字 3. mac上 source + 虚拟环境的目录/bin/activate win上 直接进入虚 ...

  4. vmware搭建linux环境

    参考博文:https://www.cnblogs.com/wuzm/p/10877990.html

  5. 使用kali中的Metasploit通过windows7的永恒之蓝漏洞攻击并控制win7系统(9.27 第十三天)

    1.开启postgresql数据库 2.msfconsole 进入MSF中 3.search 17-010 搜索cve17-010相关的exp auxiliary/scanner/smb/smb_ms ...

  6. POJ - 1065 Wooden Sticks(贪心+dp+最长递减子序列+Dilworth定理)

    题意:给定n个木棍的l和w,第一个木棍需要1min安装时间,若木棍(l’,w’)满足l' >= l, w' >= w,则不需要花费额外的安装时间,否则需要花费1min安装时间,求安装n个木 ...

  7. sourcetree安装以及跳过sourcetree注册登录 - git仓库管理工具桌面版

      腾讯软件下载:https://pc.qq.com/detail/17/detail_23237.html 官网下载:https://www.sourcetreeapp.com/   下载完直接安装 ...

  8. 17. react redux的中间件

    1. redux 数据流程图 View 会派发一个 Action Action 通过 Dispatch 方法派发给 Store Store 接收到 Action 连同之前的 State 发给  Red ...

  9. css常用技巧1

    css绘制三角形 <style> .triangle-box{ margin: 50px auto; height: 300px; width: 500px; box-shadow: 1p ...

  10. 大二暑假第三周总结--开始学习Hadoop基础(二)

    简单学习NoSQL数据库理论知识 NoSQL数据库具有以下几个特点: 1.灵活的可扩展性(支持在多个节点上进行水平扩张) 2.灵活的数据模型(与关系数据库中严格的关系模型相反,显得较为松散) 3.与与 ...