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;    
}
posted @ 2012-08-12 23:23  沐阳  阅读(371)  评论(0编辑  收藏  举报