【题解】Jury Compromise(链表+DP)

传送门

题目大意

给你\(n\le 200\)个元素,一个元素有两个特征值,\(c_i\)和\(d_i\),\(c,d \in [0,20]\),现在请你选出\(m\le 20\)个元素使得\(\sum c+\sum d\)最大,使得$|\sum c - \sum d|最小,输出\sum c \(和\)\sum d$和一组合法方案。

分析

是DP无误了。

我们可以先不考虑绝对值,平移一下值域,假如说我们知道\(\sum c +- \sum d\)就可以通过解方程解出来\(\sum c\)和\(\sum d\)了,考虑设置状态:

  • 要考虑\(m\)的限制,所以要把已经选择了多少元素记录在状态里面。
  • 要考虑\(|\sum c - \sum d|\),有绝对值不好考虑,有两个转移的方向,所以我们考虑直接把绝对值里面的值记录到状态里,也不大,\(8000\)而已。
  • 这个时候,只要考虑\(\sum c + \sum d 最大,直接DP\)

\(dp(i,j)\)表示选取了\(i\)个数之后,绝对值里面的值是\(j\)的最大的\(c_i+d_i\)为多少,转移:

\[t\text{第t个元素}:dp(i,j)=max\{dp(i-1,k-(d[t]-c[t]))\}
\]

然而我们还要记录方案,我们直接用链表,由于对于每个\((t,i,j)\),只会在链表中增加一个元素,所以空间没有问题,你输出vector的size发现只有四千多。

写得很心酸,但是还是放没有调试信息的代码出来。

最后输出方案链表操作即可。代码里的reverse是trick,因为要求方案从小往大输出。还有因为用过很多种办法,所以导致代码有无用的冗余。

但其实我是暴力过此题(时间/空间/代码长度)(笑)

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector> using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
} struct NODE{
int data;
NODE(){data=0;}
inline void clean(){
data=-0x3f3f3f;
}
}; struct DATA{
NODE data[8000+1];
inline NODE&operator[](int x){return data[x+4000];}
inline void clean(){
for(register int t=0;t<=8000;++t)
data[t].clean();
}
}dp[21]; int way[21][8000+1];
int n,m; struct E{
int data,nx;
E(){data=nx=0;}
}T;
vector < E > e;
inline void add(int&fr,int to,int data){
register E temp;
temp.data=data;
temp.nx=to;
e.push_back(temp);
fr=e.size()-1;
}
int p[201],d[201]; int main(){
int cnt=0;
while(n=qr(),m=qr(),n or m){
e.clear();
e.push_back(T);
memset(way,0,sizeof way);
for(register int t=1;t<=n;++t) p[t]=qr(),d[t]=qr();
for(register int t=0;t<=20;++t) dp[t].clean();
reverse(p+1,p+n+1),reverse(d+1,d+n+1);
dp[0][0].data=0;
for(register int t=1,delta;t<=n;++t){
delta=p[t]-d[t];
for(register int i=min(m,t)-1;i>=0;--i){
for(register int k=max(-4000,-4000+delta),edd=min(4000,4000-delta);k<=edd;++k){
NODE& fr=dp[i][k];
NODE& to=dp[i+1][k+delta];
if(fr.data>=0&&to.data<fr.data+p[t]+d[t])
to.data=fr.data+p[t]+d[t],add(way[i+1][k+delta+4000],way[i][k+4000],t);
}
}
} register int t1,t2,cur=0;
for(register int t=0;t<=4000;++t){
if(dp[m][t].data>=0||dp[m][-t].data>=0){
if(dp[m][t].data<dp[m][-t].data) t=-t;
cur=t;
t1=(dp[m][t].data-t)>>1;
t2=(dp[m][t].data+t)>>1;
break;
}
}
printf("Jury #%d \nBest jury has value %d for prosecution and value %d for defence:\n",++cnt,t2,t1);
for(register int t=way[m][cur+4000];t;t=e[t].nx)
printf(" %d",n-e[t].data+1);
putchar('\n'),putchar('\n');
}
return 0;
}
  致看我这道题代码的同学:

  本份代码历经一次编写,三次重构,最终剩下3.5k 实际上写了 10k以上

  算法使用过:套bitset 套vector 都tle了 现在用的是链表

  为了调试,本人从网上蒯了std 并且写了特制的check.cpp make.cpp 还有spj.cpp check+spj=5k

  最终发现是自己想压行却少分类讨论了一种情况

  请同学们代码WA了不要直接拍,要先看看代码里有没有粗心或者逻辑错误

【题解】Jury Compromise(链表+DP)的更多相关文章

  1. POJ 1015 Jury Compromise(dp坑)

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

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

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

  3. POJ 1015 Jury Compromise【DP】

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

  4. POJ 1015 Jury Compromise(双塔dp)

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

  5. POJ-1015 Jury Compromise(dp|01背包)

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

  6. HDU 1015 Jury Compromise 01背包

    题目链接: http://poj.org/problem?id=1015 Jury Compromise Time Limit: 1000MSMemory Limit: 65536K 问题描述 In ...

  7. ACM - 动态规划 - UVA323 Jury Compromise

    UVA323 Jury Compromise 题解 考虑用动态规划.该问题要求解的最终状态为,选出的 \(m\) 个人,使得辩方总分与控方总分差的绝对值最小,总分之和最大.即 \(\left| D(\ ...

  8. poj1015 Jury Compromise【背包】

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

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

随机推荐

  1. Scala之Future超时

    最近在开发中使用akka http进行请求,返回的是一个future,并且要对future进行超时设置,不知怎么设置,因此学习了下. 一.Future阻塞 首先,scala中的future不支持内置超 ...

  2. 2016集训测试赛(二十四)Problem C: 棋盘控制

    Solution 场上的想法(显然是错的)是这样的: 我们假设棋子是一个一个地放置的, 考虑在放置棋子的过程中可能出现哪些状态. 我们令有序整数对\((i, j)\)表示总共控制了\(i\)行\(j\ ...

  3. getServletConfig().getInitParameter("count1") java.lang.NullPointerException

    通常在doget中 System.out.println(getServletConfig()); System.out.println(getServletConfig().getInitParam ...

  4. SELinux下更改mysql端口

    默认情况下 mysql更改端口后是不能通过selinux的 提示启动错误,那么首先就要看mysql的错误日志 可是我不知道mysql错误日志的位置 首先,更改selinux的模式为passive 然后 ...

  5. 序列文件(seq_file)接口

    转载:http://blog.csdn.net/gangyanliang/article/details/7244664 内容简介: 本文主要讲述序列文件(seq_file)接口的内核实现,如何使用它 ...

  6. asp.net 面试题(附答案)

    这次面试遇到的一些问题有很基础,也有的一些我没有听过.根据经验不同或应聘职位和公司的不同等,遇到的面试问题肯定也不一样.本人两年半asp.net开发经验,这是我年后应聘asp.net工程师遇到的问题, ...

  7. struts2拦截器实现session超时返回登录页面(iframe下跳转到其父页面)

    需求:session超时时,返回登录页面,由于页面嵌套在iframe下,因此要跳转到登录页面的父页面,但是首页,登录页面等不需要进行跳转 实现: java文件:SessionIterceptor.ja ...

  8. 在网页中插入flash播放器,播放flv视频

    效果图如下: 所用代码如下: <object id="FLVPlayer" height="480" width="640" code ...

  9. 转:java工程师成神之路

    转自: http://www.hollischuang.com/archives/489 一.基础篇 1.1 JVM 1.1.1. Java内存模型,Java内存管理,Java堆和栈,垃圾回收 htt ...

  10. HTML5 Canvas 绘制佛教万字

    代码如下: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Ty ...