罗大神说这题很简单,,,,然而我着实写的很难过。。。


题目链接:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110495#problem/K

题意:

给定n个人对罪犯的d值和p值,从中选m个人使得abs(sum(d)−sum(p))最小,如果有多种情况则输出sum(p)+sum(d)最大的情况,并升序输出选择的人的编号。

分析:

这题是既要考虑差又要考虑和。还是绝对值最小。。刚看见有点懵逼。

其实不方,这题d和p最大只有20,m最大又只有20,就是说差的绝对值最大只有20 * 20,

那么我们设dp[i][j]为已经选出i个人,sum(p)−sum(d)为j的最大sum(p)+sum(d)。dp[i][j]=−1 表示这个状态无法达到。

那么问题来了,绝对值怎么处理,如果sum(p)−sum(d)小于0怎么办。。。

我们知道差的绝对值最大为20 * 20,那么我们给每个差都加上20 * 20 ,保证j大于等于0,这样就相当于以20 * 20 为原点,最终只要找到距离20 * 20 最近的dp值大于等于0的点就好了。。

想到这里就差不多了。。

很容易得到状态转移方程。

对于每个i和j的状态枚举给定的n个人,注意判断之前当前这个人之前是否出现过。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define sa(a) scanf("%d", &a)
#define sal(a) scanf("%I64d", &a)
const int maxn = 1000 + 5, maxm = 200 + 5, INF = 0x3f3f3f3f;
int p[maxm], d[maxm];
struct DP{int a; int now;};
DP dp[20 + 5][maxn];
int tt[maxn];
int cnt;
void output(int he, int ans)
{
if(he == 0) return;
int index = dp[he][ans].now;
tt[he--] = index;
output(he, ans - p[index] + d[index]);
}
bool vis(int i, int j, int k)
{
while(i >= 0){
int index = dp[i][j].now;
if(index == k) return true;
i--;
j -= p[index] - d[index];
}
return false;
}
int main (void)
{
int n, m;
int cnt = 1;
while(scanf("%d%d", &n, &m) && n + m){
for(int i = 0; i < n; i++){
sa(p[i]); sa(d[i]);
}
int t = m * 20;
for(int i = 0; i <= m; i++){
for(int j = 0; j <= 2 * t; j++){
dp[i][j].a = -1;
dp[i][j].now = -1;
}
}
dp[0][t].a = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j <= t * 2; j++){
if(dp[i][j].a < 0) continue;//状态无法到达
for(int k = 0; k < n; k++){
if(dp[i][j].a + p[k] + d[k] > dp[i + 1][j + p[k] - d[k]].a){
if(vis(i, j, k)) continue;//之前出现过
dp[i + 1][j + p[k] - d[k]].a = dp[i][j].a + p[k] + d[k];
dp[i + 1][j + p[k] - d[k]].now = k;
}
}
}
}
int i = 0;
while(dp[m][t + i].a < 0 && dp[m][t - i].a < 0) i++;
int ans;
if(dp[m][t + i].a > dp[m][t - i].a) ans = t + i;
else ans = t - i;
printf("Jury #%d\n", cnt++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",
(ans - t + dp[m][ans].a)/2, (dp[m][ans].a - ans + t)/2);
output(m, ans);
sort(tt + 1, tt + m + 1);
for(int i = 1; i <= m; i++)
printf(" %d%c", tt[i] + 1, i == m?'\n':' ');
printf("\n");
}
return 0;
}

POJ 1015 Jury Compromise【DP】的更多相关文章

  1. POJ 1015 Jury Compromise(dp坑)

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

  2. 背包系列练习及总结(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 ...

  3. POJ 1015 Jury Compromise(双塔dp)

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

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

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

  5. POJ 3280 Cheapest Palindrome【DP】

    题意:对一个字符串进行插入删除等操作使其变成一个回文串,但是对于每个字符的操作消耗是不同的.求最小消耗. 思路: 我们定义dp [ i ] [ j ] 为区间 i 到 j 变成回文的最小代价.那么对于 ...

  6. poj1015 Jury Compromise【背包】

    Jury Compromise Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:32355   Accepted:8722   ...

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

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

  8. POJ 1015 Jury Compromise dp分组

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

  9. poj 1015 Jury Compromise(背包变形dp)

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

随机推荐

  1. Win2D 入门教程 VB 中文版 - 防止内存泄漏

    避免内存泄漏 本文从微软官方文档翻译 http://microsoft.github.io/Win2D/html/RefCycles.htm 如果文档有问题,可以在 https://github.co ...

  2. Node.js Addons翻译(C/C++扩展)

    PS:请先升级Node 6.2.1,Node 升级命令 npm install -g n;n stable.NOde.js扩展是一个通过C/C++编写的动态链接库,并通过Node.js的函数requi ...

  3. SVM-支持向量机 学习 1

    参考 https://zhuanlan.zhihu.com/p/42334376 https://blog.csdn.net/liugan528/article/details/79448379 ht ...

  4. unix网络编程-配置unp.h头文件

    第一步进入:www.unpbook.com,下载unp的随书代码.新建一个目录,将压缩包拷贝到这一目录下面,然后将压缩包直接解压:tar -zxvf  压缩包名.tar.gz 完成上一步后,进入到un ...

  5. 【传智播客】Libevent学习笔记(五):基本类型和函数

    目录 00. 目录 01. 基本类型 1.1 evutil_socket_t类型 1.2 标准类型 1.3 各种兼容性类型 02. 可移植的定时器函数 03. 套接字API兼容性 04. 可移植的字符 ...

  6. iOS 6 的 Smart App Banners 介绍和使用

    iOS 6 的 Smart App Banners 介绍和使用 Denis 留言: 10 浏览:4890 文章目录[隐藏] 什么是 Smart App Banners 在你的网站添加 Smart Ap ...

  7. node.js从入门到放弃(二)

    上章讲了学习node,应该去学习什么,对这些框架去进行学习现在咋们聊聊如何用原生来进行操作 主要来讲一下events-事件触发器 events是什么东西呢?他的英文翻译,活动,事件的意思,在计算机语言 ...

  8. UVa-1585-得分

    #include <stdio.h> #include <string.h> int main() { char s[100]; int T; scanf("%d&q ...

  9. [LOJ] 分块九题 6

    单点插入,单点查询. 优化了的链表. 链表老写错,干脆用vector,也不算慢. 注意链表退化的问题,及时(比如操作根号n次)就重新建块,实测速度可以提高一倍,这还是数据随机的情况,若涉及大量同一位置 ...

  10. LINUX:关于Redis集群搭建 、和搭建项目中遇到的问题

    文章来源:http://www.cnblogs.com/hello-tl/p/7804225.html 0.Redis的简单安装 1.安装redis依赖 # yum install gcc tcl g ...