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

来源:互联网 发布:php 比特比交易平台 编辑:程序博客网 时间:2024/05/06 07:30

  一行监狱里面住着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;    }

  

0 0