第一次做dp分组的问题,百度的~~

http://poj.org/problem?id=1015

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

2 2

1 2

3 4

大概思路如下。

设dp[i][j]表示选i个人,当前的差值是j的时候,最大的和值是dp[i][j]

由于他是abs的,这样会产生相同的j。但是应该分开的,因为路径是不同的,产生的dp[i][j]那个值不应该被其他覆盖。

然后就是记录路径,

path[i][j]表示是由那个值进化而来的,即可说是上一个,也可以说是这个的值。

然后思路就是,

枚举i : 1 to m //选m个人

  k : 0 to 2 * fix //枚举差值。

    判断即可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int fix = ;
int dp[][]; // dp[i][j]表示选了i个人,差值为j的时候,的最大和值
int path[][];
int D[ + ];
int P[ + ];
int sum[ + ];
int dis[ + ];
set<int>ans;
int n, m;
void init() {
memset(dp, -, sizeof dp);
memset(path, -, sizeof path);
ans.clear();
}
void work() {
init();
for (int i = ; i <= n; ++i) {
cin >> D[i] >> P[i];
dis[i] = D[i] - P[i];
sum[i] = D[i] + P[i];
}
dp[][fix] = ; //因为fix了,所以0的时候,其实就是fix的时候
for (int i = ; i <= m; ++i) {
for (int k = ; k <= * fix; ++k) {
if (dp[i - ][k] >= ) { //如果这个状态可行,才能再选举一个人进来
for (int j = ; j <= n; ++j) {
if (dp[i - ][k] + sum[j] > dp[i][k + dis[j]]) { //加了这个人后,最优解变大,然后差值就是变成k + dis[j]的
//还需要检查j是否在dp[i - 1][k]这个路径上了。
int t = path[i - ][k];
int pre = i - ;
int ff = k;
bool flag = true;
while (t != -) {
if (t == j) {
flag = false;
break;
}
ff -= dis[t]; //减去当前这个点的值
t = path[--pre][ff];
}
if (flag == true) {
dp[i][k + dis[j]] = dp[i - ][k] + sum[j];
path[i][k + dis[j]] = j;
}
}
}
}
}
}
int i = fix;
int j = ;
while (dp[m][i + j] < && dp[m][i - j] < ) { //排除没用的状态
++j;
}
int KK; //最小的差值 对应的那个dp,可以对应输出最大的和值
if (dp[m][i + j] > dp[m][i - j]) {
KK = i + j;
} else KK = i - j;
int t = path[m][KK];
int pre = m;
int ff = KK;
while (t != -) {
ans.insert(t);
ff -= dis[t];
t = path[--pre][ff];
}
int df = , pf = ;
for (set<int> :: iterator it = ans.begin(); it != ans.end(); ++it) {
df += D[*it];
pf += P[*it];
}
static int gg = ;
printf("Jury #%d\n", ++gg);
printf("Best jury has value %d for prosecution and value %d for defence:\n", df, pf);
for (set<int> :: iterator it = ans.begin(); it != ans.end(); ++it) {
cout << " " << *it;
}
cout << endl << endl;
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
IOS;
while (cin >> n >> m && (n + m)) {
work();
}
return ;
}

POJ 1015 Jury Compromise dp分组的更多相关文章

  1. POJ 1015 Jury Compromise dp

    大致题意: 从n个候选人中选出m个人作为陪审团.为了让陪审团的选择更公平,辩方和控方都为这n个候选人给出了满意度(辩方为D[j],控方为P[j],范围0至20).现在要使得选出的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 1015 Jury Compromise(背包+方案输出)

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

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

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

  7. POJ 1015 Jury Compromise(dp坑)

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

  8. POJ 1015 Jury Compromise【DP】

    罗大神说这题很简单,,,,然而我着实写的很难过... 题目链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110495#proble ...

  9. HDU POJ 1015 Jury Compromise(陪审团的人选,DP)

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

随机推荐

  1. linux 进程学习笔记-信号semaphore

    信号灯(信号量)不是进程通信手段,其是用于控制和协调在进程间通信过程中的共享资源访问,就如同互斥锁(两者的区别可以参考这里) 可以将简单地将信号灯想象成一个计数器,初始时计数器值为n(有n个资源可供使 ...

  2. ACM学习历程—HDU1716 排列2(dfs && set容器)

    Description Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数.   Input 每组数据占一行,代表四张卡片上的数字( ...

  3. bzoj 4883 [Lydsy1705月赛]棋盘上的守卫——并查集(思路!)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4883 把各行和各列看成n+m个点. 如果一下能防守行和列,就是最大匹配了.这是每两个左右部点 ...

  4. hdu 1521 排列组合 —— 指数型生成函数

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1521 标准的指数型生成函数: WA了好几遍,原来是多组数据啊囧: 注意精度,直接强制转换(int)是舍去小 ...

  5. poj3784Running Median——堆维护中间值

    题目:http://poj.org/problem?id=3784 将较小的数放入大根堆,较大的数放入小根堆,控制较小数堆大小比较大数堆小1,则较大数堆堆顶即为中位数. 代码如下: #include& ...

  6. Docker入门(一):简介

    这个<Docker入门>系列文档,是我根据Docker官网(https://docs.docker.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家 ...

  7. TCP 登录实现代码

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  8. opencvsharp BitmapSource图片截取问题

    private BitmapSource GetUiImage(FrameworkElement ui) { RenderTargetBitmap bmp=new RenderTargetBitmap ...

  9. 6、scala面向对象-对象

    一.对象 1.object object,相当于class的单个实例,通常在里面放一些静态的field或者method,第一次调用object的方法时,就会执行object的constructor, ...

  10. Django 中得ORM介绍和字段及字段参数

    ORM 介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说 ORM 是通过使用 ...