原文
原作者 lizo_is_me

问题描述:

一个监狱里有P个并排着的牢房,从左往右一次编号为1,2,…,P。最初所有牢房里面都住着一个囚犯。现在要释放一些囚犯。如果释放某个牢房里的囚犯,必须要贿赂两边所有的囚犯一个金币,直到监狱的两端或者空牢房为止。现在要释放a1,a2,...,aQa1,a2,...,aQ号囚犯,如何选择释放的顺序,使得使用的金币最少。

思路:

其中很重要的一点:释放了某个囚犯以后,就把连续的牢房分成了没有任何关系的两段。
只要枚举出所有的释放囚犯的顺序即可,复杂度为 O(Q3)O(Q3)。

利用动态规划枚举所有的情况的时候,我们有2种方法:
方法1.(自上而下)先选取首先释放的囚犯。然后划分没两段独立的部分,然后对左右两段再递归的调用。
方法2.(自下而上)利用动态规划数组,例举出所有最小的子问题,然后再根据最小的子问题可以组合成稍大一点的子问题。

用二叉树的来表示可能更形象一点:
针对每个释放顺序,都可以用一个二叉树来表示
例如:有 1-8个囚犯,释放顺序为:4,2,6的话
1、先释放4

2、释放2

3、释放6

可以看出,当释放4号的时候,就把原先的1-8号分为1-3号和5-8号两段独立的,所以上面的第二步和第三步其实可以交换的,
当然这个例子比较简单,不过其实再复杂的问题也就是上面的这些情况的不断叠加而已,比如上面这个二叉树也可能是更大的二叉树的一个部分。

然后我们再回过来,用二叉树的表示方法来再来说一下上面的2个方法,可能方法1比较容易理解,人的一般思维方式都是这样的,然后重点说说方法2
方法2的思想是:
例如要释放 a1,a2,...,aQa1,a2,...,aQ之间的囚犯数
然后Cost[0][3]就是上面值更小的一个情况
这样不断迭代,最后就可以求出Cost[0][Q+1],就是最后的答案

枚举的时候,由于可能会出现多次相同的情况,但前面又已经计算过了,所以可以利用一个数组,来保存已经计算过的情况(剪枝)。

代码实现

//区间动态规划
//bribe the prisoner
//定义一个二维数组。依次用来填充最小的花费。
int dp[max+1][max+1];
cost[i][j]//表示从第i个填充到j个时的最小花费。
//同时定义一个存放罪犯的数组。
int a[i];
void solve()
{a[0]=0;a[Q+1]=Q+1;//为了解决边界问题。for(i=0;i<=Q;i++)cost[i][i+1]=0;//初始化,因为所有的从i到i+1的花费除去边界都是0;//循环求解。定义w表示区间的范围,w=2表示跨度为2的情况,也就是该区间里面只有一个要释放的犯人for(w=2;w<=Q+1;w++){//每次选的范围都是w,从i到j 的范围内的最小值等于从i到K加从第k到j的最小值。for(i=0;i<=Q+1;i++){//此处用到的k恰是其中的中值。int j=i+w,tmp=INT_MAX;//tmp用来保存当前区间的当前最好情况的花费金币数for(k=i+1;k<j;k++)tmp=min(tmp,dp[i][k]+dp[k][j]);cost[i][j]=tmp+a[j]-a[i]-2;//此处就是当前区间最小值。}}
}

这种思想和最优二叉查找树的算法是一样的。所以懂了这个思路再去看最有二叉树相信也能一下就理解

[dp]GCJ 2009 Bribe the Prisoners相关推荐

  1. GCJ 2009 Bribe the Prisoners

    区间DP--但是细节处理比较多,代码要一些技巧--算水题吧 #include <iostream> #include <cstdio> #include <cstring ...

  2. [区间记忆化dp入门][Bribe the Prisoners SPOJ - GCJ1C09C][Codeforces Round #505D (rated, Div. 1 + Div. 2, ba]

    Bribe the Prisoners SPOJ - GCJ1C09C 作为这类题代表,f[i][j]代表第i点到第j点单独处理的最值 这题关键:释放某个囚犯后,就把囚犯分成两段,两段互相独立 这类d ...

  3. Bribe the Prisoners SPOJ - GCJ1C09C

    滴答滴答---题目链接 贿赂囚犯 Bribe the prisoners ( 动态规划+剪枝) Problem In a kingdom there are prison cells (numbere ...

  4. Bribe the Prisoners 菜鸟的记录

    Bribe the Prisoners 题目大意 有一个监狱里有一排牢房1-P,其中住着一些囚犯.现在要释放一些囚犯Q, 当释放一个囚犯的时候,要给两边所有的囚犯每人一枚金币, 直到遇到空牢房或者尽头 ...

  5. Bribe the Prisoners——GCJ 2009 Round1C C(区间dp)

    题目:P个并排的牢房(1,2,3....P).每个牢房一个囚犯.现在要释放其中的Q个囚犯.每释放一个囚犯,就得向左给每一个相邻囚犯一枚金币,直到遇到空牢房.向右也是如此.问以什么样的顺序释放所花费的金 ...

  6. Bribe the Prisoners(GCJ 2009 Round 1C C)(dp)

    题意: 一个监狱里有P个并排着的牢房.从左至右依次编号为1,2,...,P.最初所有的牢房里都住着一个囚犯.相邻的两个牢房之间可以互通信息. 现在要释放一些囚犯.如果释放某个牢房里的囚犯,其相邻的牢房 ...

  7. GCJ 2009 Round1C C Bribe the Prisoners

    /*这题终于对了,真是感激涕零,痛苦流涕,这个故事告诉我们:前人的经验果然是有道理的,INF就不要乱设置了,就设0x3f3f3f3f就好当然,还有一个问题就是,不要随便设置long long型,因为每 ...

  8. 挑战2.7.3 Round 1C 2009 C. Bribe the Prisoners 区间dp

    题目链接: https://code.google.com/codejam/contest/189252/dashboard#s=p2 题意: 题解: 区间dp dp[i][j] 表示释放a[i]~a ...

  9. 刷题: bribe the prisoners(2009 Round 1C C)

    题目描述 In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Ce ...

最新文章

  1. python笔记本-如何用Python在笔记本电脑上分析100GB数据(上)
  2. 【MATLAB】流程控制 ( 循环结构 | for 循环 | while 循环 | 分支结构 | if end 分支结构 | if else end 分支结构 | switch case 分支结构 )
  3. 【计算理论】计算复杂性 ( 计算理论内容概览 | 计算问题的有效性 | 时间复杂性度量 | 输入表示 | 时间复杂度 )
  4. Java Iterator 接口简介和简单用法.
  5. 浅谈python异步IO,同步IO,线程与进程~
  6. 精华Java问题总结
  7. java输出变量_Java笔记1: 输入输出与变量常量
  8. MacBook写代码真香!包邮送一台!
  9. 计算机二级c语言编程题型,全国计算机等级二级C语言上机编程题题型
  10. debian之自启动程序
  11. 【进阶版】 机器学习之强化学习、蒙特卡罗、AlphaGo原理浅析(22)
  12. seaborn系列 (10) | 盒形图boxplot()
  13. iOS OC消除黄色警告⚠️ (不断的更新中...)
  14. spring mvc使用@InitBinder 标签对表单数据绑定
  15. oracle failed login count metric,Oracle Life: SQL.PLSQL Archives - 云和恩墨,成就所托!
  16. java咖啡机如何清洗_咖啡过滤器怎么清洗
  17. 2021年G1工业锅炉司炉考试平台及G1工业锅炉司炉作业考试题库
  18. whistle使用总结
  19. 【Linux】理解文件系统——软硬链接
  20. 华丽大气酷炫光斑特效LOGO展示PR片头模板

热门文章

  1. 电力行业海量数据处理如何做?看中节能、上海电气案例分享
  2. java onmouseover_[Java教程]关于onmouseover和onmouseout的bug
  3. html prefetch的原理,HTML5中rel属性的prefetch预加载功能使用
  4. OpenStack云环境数据备份方案 Freezer
  5. HTML中的单引号和双引号
  6. 初学C语言入门必读~
  7. appstore数据抓取
  8. 单一世界架构初探之时间之轴
  9. Extjs各版本的下载链接,包含ext3.4源码示例
  10. 美国研发高精度气候模型精确预测气候状况