Save__TangMonk之状态压缩

来源:互联网 发布:kafka java api 编辑:程序博客网 时间:2024/05/16 02:18

Saving Tang Monk

总时间限制:
1000ms
内存限制:
65536kB

描述
《Journey to theWest》(also 《Monkey》) is one of the Four Great Classical Novelsof Chinese literature. It was writtenby Wu Cheng’en during the Ming Dynasty. In this novel, Monkey King Sun Wukong,pig Zhu Bajie and Sha Wujing, escorted Tang Monk to India to getsacred Buddhism texts.
During thejourney, Tang Monk was often captured by demons. Most of demons wanted to eatTang Monk to achieve immortality, but some female demons just wanted to marryhim because he was handsome. So, fighting demons and saving Monk Tang is themajor job for Sun Wukong to do.
Once, TangMonk was captured by the demon White Bones. White Bones lived in a palace andshe cuffed Tang Monk in a room. Sun Wukong managed to get into the palace. Butto rescue Tang Monk, Sun Wukong might need to get some keys and kill some snakesin his way.
The palace can be described as a matrix of characters. Each characterstands for a room. In the matrix, ‘K’ represents the original position of SunWukong, ‘T’ represents the location of Tang Monk and ‘S’ stands for a room witha snakein it. Please note that there are only one ‘K’ and one ‘T’, and at mostfive snakesin the palace. And, ‘.’ means a clear room as well ‘#’ means a deadlyroom which Sun Wukong couldn’t get in.
There may be some keys of different kinds scattered in the rooms, butthere is at most one key in one room. There are at most 9 kinds of keys. A roomwith a key in it is represented by a digit(from ‘1’ to ‘9’). For example, ‘1’means a room with a first kind key, ‘2’ means a room with a second kind key,’3’ means a room with a third kind key… etc. To save Tang Monk, Sun Wukongmust get ALL kinds of keys(in other words, at least one key for each kind).
For each step, Sun Wukong could moveto the adjacent rooms(except deadly rooms) in 4 directions(north,west,south andeast), and each step took him one minute. If he entered a room in which a livingsnakestayed, he must kill the snake. Killinga snakealso took one minute. If Sun Wukong entered aroom where there is a key of kind N, Sun would get that key if and only if hehad already got keys of kind 1,kind 2 … and kind N-1.In other words,Sun Wukong must get a key of kind N before he could get a key of kind N+1 (N>=1).If Sun Wukong got all keys he needed and entered the room in which Tang Monkwas cuffed, the rescue mission is completed. If Sun Wukong didn’t get enough keys,he still could pass through Tang Monk’s room. Since Sun Wukong was a impatient monkey,he wanted to save Tang Monk as quickly as possible. Please figure out theminimum time Sun Wukong needed to rescue Tang Monk.

输入
There are several test cases.
For each case, the first line includes two integers N and M(0 < N <= 100, 0<=M<=9), meaning that the palace is a N * N matrix and Sun Wukong needed M kinds of keys(kind 1, kind 2, … kind M).
Then the N*N matrix follows.
The input ends with N = 0 and M = 0.
输出
For each test case, print the minimum time (in minute) Sun Wokong needed to save Tang Monk. If it’s impossible for Sun Wokong to complete the mission, print “impossible”.
样例输入
3 1
K.S
##1
1#T
3 1
K#T
.S#
1#.
3 2
K#T
.S.
21.
0 0
样例输出
5
impossible
8
题目的大致意思是:孙悟空要拯救唐僧,在到达唐僧的位置时必须集齐M(M<=9)把钥匙,但是有限制条件——在搜集时必须先获得1号钥匙,再获得2号钥匙…..在没有获得1号钥匙情况下,到达2号钥匙的位置只能做平地处理不能获得2号钥匙!孙悟空的位置为K,唐僧的位置为T,S(snake)所代表的的是妖怪,#是不能通过的点,.是平地!每次移动(上下左右)的时间为1,打死妖怪需要多花费1单位时间,能拯救唐僧的情况下输出最小时间。
此题所需询问的是最小时间数,所以用广搜能够解决,最主要的问题是孙悟空在行走时状态的保存!孙悟空所具有的状态是,他所在的位置(x,y),他所拥有的钥匙k,他所杀死的妖怪snk。但是他杀死的是那几个妖怪呢?所以对整个地图上的妖怪编号1…5(题中说最多不会超过5只妖怪)。对妖怪编号之后就可以状态压缩了00000,表示5只妖怪都是活的00100表示编号为3的妖怪被杀死了。这样一来孙悟空的状态就明确了。(x,y,k,snk)代表孙悟空 在地图(x,y)这个点上面所拥有的钥匙数,所杀死的妖怪。

#include<iostream>#include<algorithm>#include<queue>#include<limits>#include<cstring>using namespace std;#define D   10#define SNK  (1<<6)-1#define MAX 102struct node{    int x;    int y;    int time;    int key;    int snk;    node (int xx,int yy,int tt,int kk,int ss):x(xx),y(yy),time(tt),key(kk),snk(ss){};};char maps[MAX][MAX];int dp[MAX][MAX][D][SNK];int dir[2][4]={{1,0,0,-1},{0,1,-1,0}};int N,K;char numofsnk[MAX][MAX];int BFS(int x,int y){    queue<node> que;    dp[x][y][0][0]=1;  //初始状态    node temp(x,y,0,0,0);    que.push(temp);    while(!que.empty()){        temp=que.front();        que.pop();        for(int i=0;i<4;i++){              int tx=temp.x+dir[0][i];            int ty=temp.y+dir[1][i];            int tt=temp.time;            int tk=temp.key;            int tsnk=temp.snk;            if(tx<0 || tx>=N  || ty<0  || ty>=N ) continue;  //越界            if(dp[tx][ty][tk][tsnk]) continue; //走过            if(maps[tx][ty]=='#') continue;    //不能通过时,不拓展出新的节点            if(maps[tx][ty]=='T'){                       if(tk==K) return temp.time+1;  //找打解                dp[tx][ty][tk][tsnk]=1;                        que.push(node(tx,ty,tt+1,tk,tsnk));                continue;            }            else if(maps[tx][ty]=='.'){                dp[tx][ty][tk][tsnk]=1;                que.push(node(tx,ty,tt+1,tk,tsnk));            }            else if(isdigit(maps[tx][ty])){                if(maps[tx][ty]-'1'==tk){                    dp[tx][ty][tk][tsnk]=1;                    tk++;                    que.push(node(tx,ty,tt+1,tk,tsnk));                }                else {                    dp[tx][ty][tk][tsnk]=1;                    que.push(node(tx,ty,tt+1,tk,tsnk));                }            }            else if(maps[tx][ty]=='S'){                  if ( tsnk & (1<<(numofsnk[tx][ty]-'1'))){     //numofsnk[tx][ty] 得到snk的编号,并判断死活                       dp[tx][ty][tk][tsnk]=1;                     que.push(node(tx,ty,tt+1,tk,tsnk));                  }                  else{                    dp[tx][ty][tk][tsnk]=1;                     tsnk=  tsnk | (1<<(numofsnk[tx][ty]-'1'));  //是活的就将它杀死,用移位运算                     que.push(node(tx,ty,tt+2,tk,tsnk));                  }            }        }    }    return -1;}int main(){    int x,y;    while(cin>>N>>K  && (N!=0)){        char csnk='1';        memset(dp,0,sizeof(dp));        for(int i=0;i<N;i++)        for(int j=0;j<N;j++){            cin>>maps[i][j];            if(maps[i][j]=='K'){                x=i,y=j;                maps[i][j]='.';            }            if(maps[i][j]=='S') {                numofsnk[i][j]=csnk++;            }        }        int ans=BFS(x,y);        if(ans==-1) cout<<"impossible"<<endl;        else cout<<ans<<endl;    }    return 0;}
0 0
原创粉丝点击