贿赂囚徒 BRIBE THE PRISONERS

题目简述:监狱里要放囚徒,但是没那么简单,必须要有封口费给别的囚徒,否则她们就会大闹天宫,当遇到空牢房(因为有囚徒放出来了)或者碰壁了才会停止发放金币,问:怎样使给出的金币最少?

思路:可以用dp的做法

以下是代码(其实有个疑问,似乎不用函数做这题是做不出的?!)

 

 

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn =110;
const int mod = 0;
const int inf = 0x3f3f3f3f;

ll  t;
int n, k;
int a[maxn];
int dp[maxn][maxn];    
int num = 0;
void solve()
{
    a[0] = 0;
    a[k + 1] = n + 1;//解决边界问题
    cout << "Case #" << ++num << ": ";
    for (int i = 0; i <= k; ++i)dp[i][i + 1] = 0;//初始化
    for (int i = 2; i <= k + 1; ++i)
    {
        //每次选择的范围都是i,从j到m的范围最小数等于从j到o加从第o到m的最小值
        for (int j = 0; j + i <= k + 1; ++j)
        {
            //计算dp[i][j]

            int m = j + i, tot = inf;//tot用来保存当前区间的当前最好情况的花费金币数
            for (int o = j + 1; o < m; o++)tot = min(tot, dp[j][o] + dp[o][m]);//求最初释放囚犯的最小金币数量;
            dp[j][m] = tot + a[m] - a[j] - 2;//此处就是当前区间最小值
        }
    }
    cout << dp[0][k + 1] << endl;
}
int main()
{
    cin >> t;

    while (t--)
    {
        //memset(dp, 0, sizeof dp);
        //dp为释放ij所需的金币
        cin >> n >> k;
        for (int i = 1; i <= k; ++i)cin >> a[i];
        solve();
    }

    return 0;
}

//MOSHANG
 

 

posted @ 2020-07-14 09:54  MOSHANG_SUSIE  阅读(306)  评论(0)    收藏  举报