题目链接:http://poj.org/problem?id=1015

大概题意:

  法庭要挑选m人陪审团。先随机挑选n个公民,对于每个公民,控辩双方都有各自的“喜好度”p[ ] 和 d[ ],法庭要尽量保证陪审团的m人中控方总喜好度和辩方总喜好度的差值的绝对值尽可能小,如果最佳的结果有多个,那么就选择控辩双方总喜好度最高的那个。

解题思路:

  日常不会dp题,哭),。。。思路源于网络

  设一个二维数组 dp[i][j], i代表“使用”了几个人,j代表控辩双方喜好度之差,为了避免出现数组下标为负的情况,我们可以把j值的最后再加上20*m。

  状态转移方程:dp[ i+1 ][ j+dat[i+1] ] = min(dp[i+1][ j+dat[i+1] ] , dp[i][j]+sum[i+1] )。sum[i+1] =  p[i+1] + d[i+1], dat[i+1] = p[i+1] - d[i+1] 。

  用vector记录路径,操作方便的出奇。

  Waring: 要把选取哪个人这个循环放在最外层,不然会出现这种bug: 比如说 dp[5][y] = {1,2,3,5,6} = {1,2,3,7,8}, sum[5] + sum[6] = sum[7] + sum[8],  此时程序就有可能选择前面那个{1,2,3,5,6}这五个人,但是sum[5] 很大(大于剩下的所有sum),到了 dp[6][x]的时候,由于第5人已经被选取了,所以他无法再选择第五人,但是如果当初选择的是sum[7]+sum[8],此时就可以选择sum[5]了,很明显,后者会更优,所以程序会出bug。

AC代码:

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std; const int inf=0x7ffffff;
int dp[][];
pair<int,int> pd[];
vector<int> path[][];
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m,a,b,cases=,min_n;
while(scanf("%d%d",&n,&m)==&&n&&m){
for(int i=;i<=n;i++)
scanf("%d%d",&pd[i].first,&pd[i].second);
min_n=*m;
for(int i=;i<=m;i++){
for(int j=;j<=*m;j++){
path[i][j].clear();
dp[i][j]=-inf;
}
}
dp[][min_n]=;
for(int k=;k<=n;k++){
int dat=pd[k].first-pd[k].second, sum=pd[k].first+pd[k].second;
for(int i=m-;i>=;i--){
for(int j=;j<=*m;j++){
if(dp[i][j]>=){
if(dp[i+][j+dat]<=dp[i][j]+sum){
dp[i+][j+dat]=dp[i][j]+sum;
path[i+][j+dat]=path[i][j];
path[i+][j+dat].push_back(k);
}
}
}
}
}
a=b=;
for(int i=;i<=*m;i++){
if(dp[m][min_n+i]>=||dp[m][min_n-i]>=){
int temp;
if(dp[m][min_n+i]>dp[m][min_n-i]) temp=min_n+i;
else temp=min_n-i;
for(int l=;l<m;l++){
int ind=path[m][temp][l];
a+=pd[ind].first,b+=pd[ind].second;
}
printf("Jury #%d\n",cases++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",a,b);
for(int l=;l<m;l++) printf(" %d",path[m][temp][l]);
printf("\n\n");
break;
}
} }
return ;
}

POJ1015的更多相关文章

  1. [POJ1015]Jury Compromise

    题目大意:要求你从n个人中选出m个,每个人有两个值p[i],D[i],要求选出的人p总和与D总和的差值最小.若有相同解,则输出p总+D总最大的方案. 动态规划. 一直在想到底是n枚举外面还是m放外面, ...

  2. 【poj1015】 Jury Compromise

    http://poj.org/problem?id=1015 (题目链接) 题意 随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m 人组成陪审团.选m人的办法是:控方和辩方会根据对候选人的喜欢 ...

  3. POJ1015 动态规划

    POJ1015 问题重述: 在n个候选者中选取m个人进入陪审团.每个候选者获得两项评分:D[j],P[j].求解最佳评审团,使得在每个成员的两项评分和之差 最小的情况下,使得两项评分和之和 最大. 分 ...

  4. POJ-1015(背包变形+输出路径)

    Jury Compromise POJ-1015 推荐几个较好的介绍和理解:https://blog.csdn.net/lyy289065406/article/details/6671105 htt ...

  5. NOI题库1980 陪审团的人选(POJ1015)

    1980:陪审团的人选 总时间限制: 1000ms 内存限制: 65536kB 描述 在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑选n个人作为陪审团的候 ...

  6. POJ1015 && UVA - 323 ~Jury Compromise(dp路径)

    In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting of ...

  7. 【POJ1015】Jury compromise 多个费用的背包

    这是一道比较综合的动态规划问题. 首先,根据题目中的从N个人中选出M个人,并且要使得某个目标函数最优,可以想到是背包问题,且因为要取出M个人,人数也应该作为背包体积的一个维度. 其次,要求输出路径,因 ...

  8. poj1015 01二维背包

    /* 给定辩控双方给每个人的打分p[i],d[i], dp[j][k]表示前i个人有j个被选定,选定的人的辩控双方打分差之和是k,此状态下的最大辩控双方和 按01背包做,体积一维是1,体积二维是辩控双 ...

  9. poj-1015(状态转移的方向(01背包)和结果的输出)

    #include <iostream> #include <algorithm> #include <cstring> #include <vector> ...

  10. POJ1015陪审团(Jury Compromise)——dp+路径记录

    题目:http://poj.org/problem?id=1015 差值是有后效性的,所以“转化为可行性”,开一维记录“能否达到这个差值”. 当然可以开两维分别记录 a 和 b,但 “值只是0或1” ...

随机推荐

  1. 《Splunk智能运维实战》——1.7 为本书加载样本数据

    本节书摘来自华章计算机<Splunk智能运维实战>一书中的第1章,第1.7节,作者 [美]乔史·戴昆(Josh Diakun),保罗R.约翰逊(Paul R. Johnson),德莱克·默 ...

  2. Next.js 7发布,构建速度提升40%

    Next.js团队发布了其开源React框架的7版本.该版本的Next.js主要是改善整体的开发体验,包括启动速度提升57%.开发时的构建速度提升40%.改进错误报告和WebAssembly支持. \ ...

  3. 在服务器上发布第一个.net项目

    作为一名前端开发者,对后端一窍不通可是不行的.公司后端所用的恰好是.net技术,日常开发常见MVC架构,然而还是对MVC不甚了解,前端开发也多有掣肘.本人很想摸索清楚如何构建一个asp.net的项目, ...

  4. mpvue开发微信小程序之时间+日期选择器

    最近在做微信小程序,技术栈为mpvue+iview weapp组件库. 因项目需求,要用到日期+时间选择器,iview组件库目前还未提供时间日期选择器的组件,小程序官方组件日期时间也是分开的,在简书上 ...

  5. mysql的group by

    Group By 有几个规律: Group by的语法:"Group by <字段>“意为按照字段进行分类汇总.这里需要注意四点:        (1)按照你的分类要求Group ...

  6. 自己动手在Linux系统实现一个everything程序

    大家好,我是良许. 我们知道,在 Windows 下,有一款非常实用的神器,叫作 Everything ,它可以在极短的时间里,搜索出来你所想要的文件/目录,如下图示: Linux 下也有一些类似于 ...

  7. JAVA实现拼手气红包算法

    实现拼手气红包算法,有以下几个需要注意的地方: 抢红包的期望收益应与先后顺序无关 保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如 ...

  8. 09JAVA基础-常用类

    1.Scanner //获取键盘输入 Scanner sc = new Scanner(System.in); int num = sc.nextIn(); String str = sc.nextL ...

  9. 重要的serialVersionUID

    所有序列化的DO都需要加上 serialVersionUID 否则未来可能就有一个坑在等着你 当你需要修改序列化的实体累的时候 之前缓存内容反序列化就会失败,如果这个缓存很多个地方都在存取 使用 那么 ...

  10. 【SMB源码解析系列】——002.RESET中断

    跟随代码结尾处的中断向量,我们可以看到RESET中断所在地址为Start标签处. 这部分代码比较简单,从字面便可基本理解. 1.(682~683)状态寄存器设置,sei指令用于禁用IRQ中断,SMB中 ...