您的位置:首页 > 其它

130_Bribe the Prisoners 囚徒贿赂问题 (2009 Round1C C)

2016-01-08 08:25 211 查看
一行监狱里面住着P个连续的囚徒,现在有一些囚徒需要释放,但是如果释放囚徒则需贿赂两边所有相邻的囚徒(直到遇到空位或者数组越界),求贿赂的最小值。

此题用动态规划来解决:

dp[i] [j] 表示释放A(i) 到A(j)的所有囚犯,但不包括A(i) 和A(j),假定A(i) 和A(j)已经被释放,那么就形成两个空位。

释放期中一个囚徒,花费有如下三个方面组成:

1.自己的花费(区间长度);

2.释放所有左区间里所需要释放囚徒的花费;

3.释放所有右区间里所需要释放囚徒的花费;

只需要不断枚举下一个在区间内囚徒的被释放的总花费花费,找到其最小值,再加上区间长度,便可得到总的花费的最小值。

注意的是必须把两面“墙壁”添加到囚徒数组中,因为他们是两个空位,所有的囚徒都在其间,

所以,dp[0][Q+1]包含了所有囚徒,即为所求的最小值。

题源来自《挑战程序竞赛》第二版 130页。

//
//  130_bribe the prisoners.cpp
//  changlle
//
//  Created by user on 1/7/16.
//  Copyright (c) 2016 user. All rights reserved.
//

#include <iostream>
using namespace std;
const int INF=10000;

int P=20;
int Q=3;
int A[5]={0,3,6,14,21};

int dp[5][5];

void solve() {

A[0]=0;
A[Q+1]=P+1; //添加墙壁,由此可以包含所有囚徒

for (int q=0;q<=Q;q++)
dp[q][q+1]=0;//初始化,紧挨着的囚徒之间没有需要释放的囚徒

for (int w=2; w<=Q+1;w++){
for (int i=0; i+w<=Q+1;i++){
//计算dp[i][j]
int j=i+w, t=INF;

for (int k=i+1;k<j;k++)
t=min(t,dp[i][k]+dp[k][j]);

dp[i][j]=t+A[j]-A[i]-2;

}

}

}

int main() {

solve();
cout<<dp[0][Q+1]<<endl;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: