Bribe the Prisoners(GCJ 2009 Round 1C C)(dp)
2017-08-29 15:01
375 查看
题意:
一个监狱里有P个并排着的牢房。从左至右依次编号为1,2,...,P。最初所有的牢房里都住着一个囚犯。相邻的两个牢房之间可以互通信息。
现在要释放一些囚犯。如果释放某个牢房里的囚犯,其相邻的牢房里的囚犯就会知道,因而发生暴动。所以,释放某个囚犯时,必须要贿赂两旁相邻牢房的囚犯一枚金币。另外,为了防止释放的消息在相邻牢房间传开,不仅两旁直接相邻的牢房,所有可能听到消息的囚犯,即直到空牢房为止或直到监狱两端为止,此间的所有囚犯都必须给一枚金币。
现在要释放Q名囚犯。如果选择所需金币数量尽量少的顺序释放,最少需要多少枚金币?
释放的Q名囚犯,显然会将整个区间分成许多小区间,以此为思路,我们用dp[i][j]表示:将从a[i]号囚犯到a[j]号囚犯(不含两端的囚犯)的连续部分里的所有囚犯都释放时,所需的最少金币总数。
为了更方便的处理两端的情况,我们把左端当成0号囚犯,右端当成Q + 1号囚犯。这样,dp[0][Q + 1]就是答案。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10000 + 10;
const int INF = 10000000;
int P, Q, a[maxn]; //A中保存输入数据,下标从1开始
int dp[maxn][maxn]; //dp[i][j] := 释放(i, j)所需的金币
int main()
{
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++){
scanf("%d%d", &P, &Q);
for (int i = 1; i <= Q; i++){
scanf("%d", &a[i]);
}
//为了方便,将两端加入a中
a[0] = 0;
a[Q + 1] = P + 1;
//初始化
for (int q = 0; q < Q; q++){
dp[q][q + 1] = 0;
}
//从短的区间开始填充dp
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]);
}
//最初的释放还需要与所释放囚犯无关的a[j] - a[i] - 1 - 1枚金币
dp[i][j] = t + a[j] - a[i] - 1 - 1;
}
}
printf("Case #%d: %d\n", cas, dp[0][Q + 1]);
}
return 0;
}
一个监狱里有P个并排着的牢房。从左至右依次编号为1,2,...,P。最初所有的牢房里都住着一个囚犯。相邻的两个牢房之间可以互通信息。
现在要释放一些囚犯。如果释放某个牢房里的囚犯,其相邻的牢房里的囚犯就会知道,因而发生暴动。所以,释放某个囚犯时,必须要贿赂两旁相邻牢房的囚犯一枚金币。另外,为了防止释放的消息在相邻牢房间传开,不仅两旁直接相邻的牢房,所有可能听到消息的囚犯,即直到空牢房为止或直到监狱两端为止,此间的所有囚犯都必须给一枚金币。
现在要释放Q名囚犯。如果选择所需金币数量尽量少的顺序释放,最少需要多少枚金币?
释放的Q名囚犯,显然会将整个区间分成许多小区间,以此为思路,我们用dp[i][j]表示:将从a[i]号囚犯到a[j]号囚犯(不含两端的囚犯)的连续部分里的所有囚犯都释放时,所需的最少金币总数。
为了更方便的处理两端的情况,我们把左端当成0号囚犯,右端当成Q + 1号囚犯。这样,dp[0][Q + 1]就是答案。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10000 + 10;
const int INF = 10000000;
int P, Q, a[maxn]; //A中保存输入数据,下标从1开始
int dp[maxn][maxn]; //dp[i][j] := 释放(i, j)所需的金币
int main()
{
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++){
scanf("%d%d", &P, &Q);
for (int i = 1; i <= Q; i++){
scanf("%d", &a[i]);
}
//为了方便,将两端加入a中
a[0] = 0;
a[Q + 1] = P + 1;
//初始化
for (int q = 0; q < Q; q++){
dp[q][q + 1] = 0;
}
//从短的区间开始填充dp
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]);
}
//最初的释放还需要与所释放囚犯无关的a[j] - a[i] - 1 - 1枚金币
dp[i][j] = t + a[j] - a[i] - 1 - 1;
}
}
printf("Case #%d: %d\n", cas, dp[0][Q + 1]);
}
return 0;
}
相关文章推荐
- Bribe the Prisoners——GCJ 2009 Round1C C(区间dp)
- GCJ 2009 Round1C C Bribe the Prisoners
- Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)
- Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)
- Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)
- Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)
- GCJ 2009 Round 1C C (Bribe the Prisoners)
- 挑战2.7.3 Round 1C 2009 C. Bribe the Prisoners 区间dp
- GCJ 2009 Round 1C Bribe the Prisoners
- GCJ--Bribe the Prisoners (2009 Round 1C C)
- GCJ 2009 Bribe the Prisoners
- 刷题: bribe the prisoners(2009 Round 1C C)
- 130_Bribe the Prisoners 囚徒贿赂问题 (2009 Round1C C)
- 记忆化搜搜——Code Jam 2009 Round 1C #C Bribe the Prisoners
- 129_Bribe the Prisoners_DP
- DP-记忆化dp--Bribe the Prisoners
- GCJ Round 1C 2009 Problem C. Bribe the Prisoners
- Codeforces Round #360 (Div. 2) -- E. The Values You Can Make (DP)
- Codeforces Beta Round #2_B. The least round way(DP)
- [DP 平衡树] Codeforces 809D Round #415 (Div. 1) D. Hitchhiking in the Baltic States