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;    

}

你可能感兴趣的:(HDU)