[Poj 1015] Jury Compromise 解题报告 (完全背包)
题目链接:http://poj.org/problem?id=1015
题目:
题解:
我们考虑设计DP状态(因为这很显然是一个完全背包问题不是吗?)
dp[j][k]表示在外层循环到i时,选了j个人,此时辩方总分和控方总分差值为k的时,辩方和控方的总分的和的最大值
dp[j][k+a[i]-b[i]] = max (dp[j][k + a[i] - b[i]] , dp[j][k] + a[i] + b[i])
因为是完全背包,所以我们需要写一个search函数判断当前转移的状态是否已经选过了i,这样我们需要记录一个d[j][k]数组表示在dp[j][k]的状态是选哪一个人转移过来的,这恰好也是题目要求我们处理出来的
题解其实就是上述部分了
题外话:
我们考虑不写那个search函数,然后把j这一维倒序循环,根据《算法竞赛进阶指南》,这样的做法是可以的,但是笔者尝试之后还做不到,碰到的问题就是假设dp[j][k+a[i]-b[i]]被dp[j-1][k]转移得到,此时我们可以确定dp[j-1][k]这个状态没有选择i这个人。
但是在之后的循环中,dp[j-1][k]可能会被再次更新,我们要是只是统计答案的话这并没有什么影响,但是我们在d数组回溯的时候就会得到错误的转移,因为dp[j-1][k]可能被i更新,于是d[j-1][k]变成了i。补充:但是在我的AC代码里,显然是可以避免这种情况的,因为dp[j-1][k]不可能再被更新
除此之外,我发现i循环放在最外面是不行的。这是为什么?若是有读者知道请在评论区留言。
AC代码(加了search函数)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; int n,m,fix,time;
int a[],b[],dp[][],d[][],id[];
inline int read()
{
char ch=getchar();
int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
bool search(int j,int k,int i)
{
while (j&&d[j][k]!=i)
{
int o=d[j][k];
k-=a[o]-b[o];
j--;
}
if (j) return false;
return true;
}
int main()
{
while ()
{
n=read();m=read();
if (!n) break;
for (int i=;i<=n;i++)
{
a[i]=read();b[i]=read();
}
memset(dp,-,sizeof(dp));
memset(d,,sizeof(d));
fix=m*;
dp[][fix]=;
for (int j=;j<=m;j++)
for (int k=;k<=fix<<;k++)
if (dp[j-][k]>=)
{
for (int i=;i<=n;i++)
if (dp[j-][k]+a[i]+b[i]>dp[j][k+a[i]-b[i]]&&search(j-,k,i))
{
dp[j][k+a[i]-b[i]]=dp[j-][k]+a[i]+b[i];
//if (j==3&&k+a[i]-b[i]==57&&k==58) printf("sdfs%d\n",d[j-1][k]);
d[j][k+a[i]-b[i]]=i;
//if (j==2&&k+a[i]-b[i]==58) printf("%d\n",i);
}
}
int k,div;
for (int i=;i<=fix;i++)
if (dp[m][fix-i]!=-||dp[m][fix+i]!=-) {k=i;break;}
//printf("%d\n",k);
div=dp[m][fix-k]>dp[m][fix+k]?(fix-k):(fix+k);
printf("Jury #%d\n",++time);
printf("Best jury has value %d for prosecution and value %d for defence:\n",(dp[m][div]+div-fix)/,(dp[m][div]-div+fix)/);
int r=div;
for (int i=;i<=m;i++)
{
id[i]=d[m-i+][r];
r-=a[id[i]]-b[id[i]];
}
sort(id+,id++m);
for (int i=;i<=m;i++) printf(" %d",id[i]);
printf("\n\n");
}
return ;
}
[Poj 1015] Jury Compromise 解题报告 (完全背包)的更多相关文章
- 背包系列练习及总结(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 ...
- poj 1015 Jury Compromise(背包+方案输出)
\(Jury Compromise\) \(solution:\) 这道题很有意思,它的状态设得很...奇怪.但是它的数据范围实在是太暴露了.虽然当时还是想了好久好久,出题人设了几个限制(首先要两个的 ...
- OpenJudge 2979 陪审团的人选 / Poj 1015 Jury Compromise
1.链接地址: http://bailian.openjudge.cn/practice/2979 http://poj.org/problem?id=1015 2.题目: 总Time Limit: ...
- POJ 1015 Jury Compromise(双塔dp)
Jury Compromise Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33737 Accepted: 9109 ...
- POJ 1015 Jury Compromise 2个月后重做,其实这是背包题目
http://poj.org/problem?id=1015 题目大意:在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑选n个人作为陪审团的候选人,然后再从 ...
- poj 1015 Jury Compromise(背包变形dp)
In Frobnia, a far-away country, the verdicts in court trials are determined by a jury consisting of ...
- POJ 1015 Jury Compromise dp分组
第一次做dp分组的问题,百度的~~ http://poj.org/problem?id=1015 题目大意:在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑 ...
- POJ #1015 - Jury Compromise - TODO: POJ website issue
(poj.org issue. Not submitted yet) This is a 2D DP problem, very classic too. Since I'm just learnin ...
- POJ 1015 Jury Compromise
感觉此题略难...... 背包问题.据说有一种二维DP的写法是错的.亲测,背包做法无误. dp[i][j][k]表示前i个物品,选择j个,差值为k的情况下获得的最大总和 dp[i][j][k]=max ...
随机推荐
- echarts 柱状图和饼状图动态获取后台数据
运用echarts来实现图表 1.首先下载echarts包 http://echarts.baidu.com/echarts2/doc/example.html,在这里我下载的是 2.将echart ...
- windows编译ffmpeg出现gcc is unable to create an executable file 的普通情况
近期有个朋友在编译ffmpeg的时候出现这个问题,他非常郁闷. 我就说,为什么我弄的时候就没问题呢??直接./configure +加上后面的參数 安全度过. 然后,我就想了,预计他的gcc的系统变量 ...
- c++:数据类型的推断type_traits
//推断左值右值引用 void main() { int i(10);//i是左值 有内存实体 int &ri(i); int &&rri(i + 5);//右值引用 cout ...
- 去除iframe滚动条1
主页面的IFRAME中添加:scrolling="yes" 子页面程序代码: 让竖条消失: <body style='overflow:scroll;overflow-x:a ...
- 137.CPP自带异常
#include <iostream> #include <exception> using namespace std; //继承自带的异常 class sizeerror ...
- vue keep-alive保存路由状态2 (高级用法,接上篇)
接上篇 https://www.cnblogs.com/wangmaoling/p/9803960.html 本文很长,请耐心看完分析. 4.高级用法,指定从什么组件进入才缓存,以及销毁缓存:先介绍我 ...
- Android TextView加下划线的几种方式
如果是在资源文件里: <resources> <</u></string> <string name="app_name">M ...
- (转载)RecyclerView之ItemDecoration由浅入深
RecyclerView之ItemDecoration由浅入深 作者 小武站台 关注 2016.09.19 18:20 字数 1155 阅读 10480评论 15喜欢 91赞赏 3 译文的GitHub ...
- js字符串日期yyyy-MM-dd转化为date示例代码
最近遇到一个问题,就是获取表单中的日期往后台通过json方式传的时候,遇到Date.parse(str)函数在ff下报错: NAN 找了些资料,发现是由于Date.parse()函数对日期格式有要求: ...
- Jlink如何校验Hex
打开SEGGER J-Flash ARM,记住必须设置好工程属性后才能校验,否则校验和为0 设置好工程属性后,直接将Hex拖入到工程中即可.在LOG窗口中会显示CRC的值 如何校验芯片中的程序的版本号 ...