hdu 5025 Saving Tang Monk | 最短路、状态压缩

来源:互联网 发布:win7设置禁止安装软件 编辑:程序博客网 时间:2024/05/29 17:54

题意:

悟空救唐僧。要按顺序取到m把钥匙去求唐僧,每把钥匙可以有多个。途中会遇到蛇,蛇会多耗费一单位时间。给出分布图,让你求出悟空求出唐僧最少所需的时间。

思路:

搜索(SPFA)、状态压缩。

定义状态dis[x][y][key][snake]:表示走到(x,y),已经拿到了前key把钥匙,砍了snake条蛇的最短距离。

因为snake最大为5,事先把蛇给标上1,2,3…运用状态压缩即可。

AC代码:

#include <cstring>#include <cstdlib>#include <cstdio>#include <iostream>#include <queue>using namespace std;const int MAXN = 105;const int MAXSNAKE = 1<<5;const int MAXKEY = 10;const int INF = 0x3f3f3f3f;const int MAXDIR = 4;int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}};int dis[MAXN][MAXN][MAXKEY][MAXSNAKE];bool vis[MAXN][MAXN][MAXKEY][MAXSNAKE];         //vis = if in queue;char gra[MAXN][MAXN];int key[15];int n, m;int cot_snake;struct Point{        int x, y, key, snake;};struct Item{        int x, y, rank;}snake[8];int getSnakeRank(int x, int y){        for(int i = 0;i < cot_snake; i++)                if(snake[i].x == x && snake[i].y == y)  return snake[i].rank;}void SPFA(int x, int y){        queue <Point> q;        q.push((Point){x, y, 0, 0});        vis[x][y][0][0] = true;        dis[x][y][0][0] = 0;        while(!q.empty())        {                Point e = q.front();                q.pop(), vis[e.x][e.y][e.key][e.snake] = false;                int x, y, key, snake, dd = 0;                for(int i = 0;i < MAXDIR; i++)                {                        x = e.x + dir[i][0], y = e.y + dir[i][1];                        int &curd = dis[e.x][e.y][e.key][e.snake];                        if(x >= 0 && y >= 0 && x < n && y < n && gra[x][y] != '#')                        {                                //cheak if snake                                if(gra[x][y] == 'S')                                {                                        int trank = getSnakeRank(x, y);                                        if(e.snake & (1<<trank))                                        {                                                dd = 1;                                                snake = e.snake;       //ever kill                                        }                                        else                                        {                                                dd = 2;                                                snake = e.snake ^ (1<<trank);                                        }                                        key = e.key;                                }                                else if(gra[x][y] >= '1' && gra[x][y] <= '9')                                {                                        int val = gra[x][y] - '0';                                        key = val-e.key == 1 ? e.key+1 : e.key;                                        snake = e.snake;                                        dd = 1;                                }                                else                                        key = e.key, snake = e.snake, dd = 1;                                //                                int &nextd = dis[x][y][key][snake];                                if(curd+dd < nextd)                                {                                        nextd = curd+dd;                                        if(!vis[x][y][key][snake])                                        {                                                q.push((Point){x, y, key, snake});                                                vis[x][y][key][snake] = true;                                                //cout<<"x = "<<x<<" y = "<<y<<endl;                                        }                                }                        }                }        }}int main(){        while(scanf("%d%d", &n, &m) != EOF)        {                //init                memset(vis, false, sizeof(vis));                memset(dis, INF, sizeof(dis));                memset(key, 0, sizeof(key));                cot_snake = 0;                if(n == 0 && m == 0)    break;                //input                getchar();                Item k, t;                for(int i = 0;i < n; i++)                {                        scanf("%s", gra[i]);                        for(int j = 0;j < n; j++)                        {                                if(gra[i][j] == 'K')    k.x = i, k.y = j;                                else if(gra[i][j] == 'T')       t.x = i, t.y = j;                                else if(gra[i][j] == 'S')       snake[cot_snake] = (Item){i, j, cot_snake}, cot_snake++;                        }                }                //solve                SPFA(k.x, k.y);                int res = INF;                for(int i = 0;i < (1<<cot_snake); i++)                        res = min(res, dis[t.x][t.y][m][i]);                if(res == INF)                        puts("impossible");                else                        printf("%d\n", res);        }        return 0;}



0 0