1057 - Collecting Gold (状态压缩DP)

题目大意:
给你一个矩阵,'x'是你的起始位置, 'g'是宝藏的位置,问最少多少步可以把所有的宝藏取完,并且最后返回起始位置。
注意:没有宝藏的时候输出 0
 
====================================================================================
 
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
const int INF = 1e9+7;
const int MAXN = 40000;
int dp[MAXN][20], m, n, k;///状态,当前所在的位置
char maps[30][30];
struct Point
{
    int x, y;
}P[20], Star;

int GetLen(Point A, Point B)
{
    int len = min(abs(A.x-B.x),abs(A.y-B.y));
    len += max(abs(A.x-B.x),abs(A.y-B.y)) - len;
    return len;
}

int DFS(int sta,int x)///状态, 现在所在的位置
{
    if(dp[sta][x] != -1) return dp[sta][x];

    dp[sta][x] = INF;
    for(int i=0; i<k; i++)
    {
        if( (sta&(1<<i)) && i != x)
        {
            dp[sta][x] = min(dp[sta][x], DFS(sta-(1<<x), i)+GetLen(P[x],P[i]));
        }
    }
   // printf("dp[%d][%d] = %d\n", sta, x, dp[sta][x]);
    return dp[sta][x];
}


int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d %d",&n, &m);
        k = 0;
        memset(dp, -1, sizeof(dp));
        for(int i=0; i<n; i++)
        {
            scanf("%s", maps[i]);
            for(int j=0; j<m; j++)
            {
                if(maps[i][j] == 'g')
                    P[k].x = i, P[k++].y = j;
                if(maps[i][j] == 'x')
                    Star.x = i, Star.y = j;
            }
        }

        for(int i=0; i<k; i++)
        {
            int sta = 1<<i;
            dp[sta][i] =  GetLen(Star, P[i]);
        }

        int ans = INF, Lim = (1<<k)-1;
        for(int i=0; i<k; i++)///最后停留的位置
            ans = min(ans,DFS(Lim,i)+GetLen(Star,P[i]));
        if(k == 0)
            ans = 0;
        printf("Case %d: %d\n", cas ++, ans);
    }
    return 0;
}

 

posted @ 2015-10-29 09:59  向前走丶不回首  阅读(174)  评论(0编辑  收藏  举报