HDU-越狱 DP Or 记忆化搜索
这题要注意的就是要构造出两个端点出来,然后直接开辟状态dp[i][j]表示i,j之间的囚犯都救出的最少的金币数,注意此时的边界i,j是不取的。初始条件是dp[i][i+1] = 0.
代码如下:
#include <cstring> #include <cstdlib> #include <cstdio> #include<iostream> using namespace std; const int inf = 0x3fffffff; int N, P, loc[105], dp[105][105]; int dfs(int a, int b) { if(b - a == 1) return 0; if (dp[a][b] ) return dp[a][b]; int ret = inf; for(int c = a+1; c < b; c++){ ret = min(ret,dfs(a,c)+dfs(c,b)+(loc[b]-loc[a])-2 ); } dp[a][b] = ret; return ret; } int main() { int T, ca = 1; for (scanf("%d", &T); ca <= T; ++ca) { scanf("%d %d", &N, &P); loc[0] = 0; loc[P+1] = N+1; for (int i = 1; i <= P; ++i) { scanf("%d", &loc[i]); // 记录囚犯的位置 } P += 1; memset(dp,0,sizeof(dp)); /* for(int gap = 2; gap <= P; gap++){ for(int a = 0; a+gap <= P; a++){ int b = a+gap; int ret = inf; for(int c = a+1; c < b; c++){ ret = min(ret,dp[a][c]+dp[c][b]+(loc[b]-loc[a]-2)); } dp[a][b] = ret; } } */ // printf("Case #%d: %d\n", ca, dp[0][P]); printf("Case #%d: %d\n", ca, dfs(0, P)); } return 0; }