/*
translation:
总共有p个犯人,其中要释放q个。但是释放一个犯人必须给两排直接相邻的牢房的犯人一枚金币。
直到空牢房为止,或者监狱的两端。求q个犯人全部释放最少需要多少金币?
solution:
区间dp
dp[i][j]表示释放i+1~j-1的犯人需要多少金币。
dp[i][j] = 此时所需金币数量 + 释放右侧部分需要的金币 + 释放左侧部分需要的金币
note:
注意循环的边界,区间dp的题目如果需要在两端设置一个值用来处理两端的情况时,此时dp[i][j]
表示的是一个开区间,所以这时候的边界处理特别容易出错,要注意!!
date:
2016.9.6
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 105;
const int INF = 1e30;
int p, q, a[maxn]; //监狱犯人总个数,释放犯人个数,释放犯人的编号
int dp[maxn][maxn];
int main()
{
freopen("C-large-practice.in", "r", stdin);
freopen("C-large-practice.out", "w", stdout);
int T, kase = 0;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &p, &q);
for(int i = 1; i <= q; i++) scanf("%d", &a[i]);
a[0] = 0; a[q + 1] = p + 1;
q += 2;
memset(dp, 0, sizeof(dp));
for(int gap = 2; gap < q; gap++) {
for(int i = 0; i + gap < q; i++) {
int j = i + gap, 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;
}
}
printf("Case #%d: %d\n", ++kase, dp[0][q - 1]);
}
return 0;
}
gcj2009R1C_C(区间dp)
最新推荐文章于 2020-12-03 21:18:35 发布