编程题-贿赂囚犯(Bribe the prisoners)-动态规划|剪枝

转载请注明出处:http://blog.csdn.net/Lizo_Is_Me/article/details/43735509

问题描述:

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

思路:

其中很重要的一点:释放了某个囚犯以后,就把连续的牢房分成了没有任何关系的两段。

只要枚举出所有的释放囚犯的顺序即可,复杂度为 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,...,aQ囚犯,我们记为A[1]-A[Q],先分成最小的区间开始找,为了方便,我们把两端也加入,这样变为A[0]-A[Q+1]

什么叫最小的区间?就是在区间里面只有一个要释放的囚犯,这样的区间(长度为2)是 A[0]?A[2],A[1]?A[3]..A[Q?1]?A[Q+1],求出其对应的金币,我们记为Cost[0][2],Cost[1][3]...Cost[Q?1][Q+1]

然后我们再找区间里面只有两个要释放的囚犯,这样区间(长度为3)可以用上面长度为2的区间来求得 例如 A[0]-A[3]

如果先释放1号,对应的是Cost[1][3]加上a0与a1之间的囚犯数

如果先释放2号,对应的是Cost[0][2]加上a2与a3之间的囚犯数

然后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;//此处就是当前区间最小值。
        }
    }
}

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

时间: 2024-10-25 06:21:20

编程题-贿赂囚犯(Bribe the prisoners)-动态规划|剪枝的相关文章

笔试编程题必杀技——动态规划

在笔试编程题中,最常见题型莫过于动态规划了,以前一直不太清楚,今天下定决心好好梳理一番. 动态规划是通过组合子问题的解决而解决整个问题的,一个大问题分解成一个小问题,这个小问题再分成小问题,以此类推,直至求出最终结果. 首先看一个把我虐了无数遍的问题:最大子数组的问题. 题目:一个有N个整数元素的一位数组(A[0], A[1],...,A[n-1], A[n]),这个数组当然有很多子数组,那么数组之和的最大值是什么呢? 例如:有数组int A[5] = {-1, 2, 3, -4, 2}:符合条

GCJ 2009 Round 1C Bribe the Prisoners

Bribe the Prisoners no tags     Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall with a wind

GCJ1C09C - Bribe the Prisoners

GCJ1C09C - Bribe the Prisoners Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall with a windo

美团点评2017秋招笔试编程题

美团点评2017秋招笔试编程题 1, 大富翁游戏,玩家根据骰子的点数决定走的步数,即骰子点数为1时可以走一步,点数为2时可以走两步,点数为n时可以走n步.求玩家走到第n步(n<=骰子最大点数且是方法的唯一入参)时,总共有多少种投骰子的方法. 题解: 写出前面的几个, 1 -> 1;   2 -> 2 ;  3 -> 4;   4 -> 8; 5 -> 16; 6 -> 32; 可以得到是 二的 n-1 次幂. #include <cstdio> int

笔试:编程题

0,1背包问题: 定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值: 递推关系式: 1) j<w(i)      V(i,j)=V(i-1,j) 2) j>=w(i)     V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) } 参考:动态规划-01背包问题 网易2017春招笔试编程题集合: 双核处理: 两个CPU,多个任务:求最小时间: 输入: 5 3072 3072 7168 3072 1024 输出: 9216 解法: 动态规划问题:以总

腾讯编程题

这是一个腾讯笔试的编程题: 我们常常会用到一个LCS的问题,本题的唯一的一个巧妙之处在于,最后求解的字符串变为的是原来的字符串与其reverse之后的字符串的最大LCS,这样本题就得到了解决. 最长公共子序列求解:递归与动态规划方法 在做OJ题目的时候,经常会用到字符串的处理.例如,比较二个字符串相似度.这篇文章介绍一下求两个字符串的最长公共子序列. 一个字符串的子序列,是指从该字符串中去掉任意多个字符后剩下的字符在不改变顺序的情况下组成的新字符串. 最长公共子序列,是指多个字符串可具有的长度最

网易2017春招笔试真题编程题集合题解

01 双核处理 题目 一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务.n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间. 输入描述 输入包括两行:第一行为整数n(1 ≤ n ≤ 50)第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数. 输出描述输出一个整数,表示最少需

Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)

Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall with a window separates adjacent cells, and

POJ C程序设计进阶 编程题#3:运算符判定

编程题#3:运算符判定 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 两个整数 a 和 b 运算后得到结果 c.表示为:a ? b = c,其中,?可能是加法 +,减法 -,乘法 *,整除 / 或 取余 %.请根据输入的 a,b,c 的值,确定运算符.如果某种运算成立,则输出相应的运算符,如果任何运算都不成立,则输出 error. 例如: 输入: 3,4,5 输出: er