POJ 3346 Treasure of theChimp Island(BFS)

来源:互联网 发布:java download failed 编辑:程序博客网 时间:2024/05/16 15:35

POJ 3346 Treasure of theChimp Island(BFS)

http://poj.org/problem?id=3346

题意:

       有一个迷宫,有宝藏,你必须从迷宫边缘进去,迷宫边缘的门有可能让你携带0-9颗炸弹,在迷宫里面有’.’表示空地,你走过空地不需要花任何时间,有’*’表示不可行格子,你就算用炸弹也不能走到这种格子上.还有标记了数字的格子,这种格子如果你消耗一颗炸弹可以立即通过不花时间,你也可以花数字上的天数(1-9)天来打开障碍.问你从边缘到达宝藏的最短时间,如果宝藏不可到达则输出” IMPOSSIBLE”

分析:

       首先我们可以想到以坐标+当前携带的炸弹数目作为一个状态.那么我们从迷宫的边缘入口依次添加初始状态到队列Q中.

       然后我们开始从Q中取出每个状态并且向4个方向扩展,每个方向如果是’.’就直接走即可,如果是数字就要考虑是炸开还是花时间打开了.如果是炸开,要注意你要判断的是炸开后炸弹数-1的那个状态时候之前已经存在.注意:由于用了nTNT炸弹数作为状态描述的一部分,所以你可以刚炸开一个墙然后往前走了一步之后,又可以回头走到墙上,此时需要再炸一次(其实这就是炸弹走了回头路),不过没关系,就算走了回头路,也就是多了一些状态最终还是会收敛的.

       如果你是花时间打开墙的话就不会走回头路,check函数会帮你把这个回头路过滤掉.

       如果下一个格子是’#’,那就不能走.

       如果下一个格子是’$’,那么就用当前time更新ans.且不用计算后继状态了,没有意义.(剪枝)

       (其实如果某个节点所花的时间time已经==当前最优解ans,直接可以剪枝,不用加到队列中去了)

AC代码:

#include<cstdio>#include<cstring>#include<ctype.h>using namespace std;const int maxn=1000000+3;const int maxr=110;//如果开105就是 runtimeerrorconst int maxc=110;int R,C;int dr[]={-1,1,0,0};//上,下,左,右int dc[]={0,0,-1,1};struct node{    int r,c,nTNT;    int time;    node(){}    node(int r,int c,int nTNT,int time):r(r),c(c),nTNT(nTNT),time(time){}}Q[maxn];//队列int state[maxr][maxc][27];//记录到达该状态的最小时间bool check(int r,int c,int nTNT,int t){    return (state[r][c][nTNT]==-1 || state[r][c][nTNT]>t);}char map[maxr][maxc];//保存地图信息int BFS(){    int front=0,tail=0;    int ans=1000000;    memset(state,-1,sizeof(state));    for(int i=0;i<R;i++)                        //边缘入口进队列    for(int j=0;j<C;j++)if(isupper(map[i][j]) || map[i][j]=='#')    {        Q[tail].r=i;        Q[tail].c=j;        Q[tail].nTNT=map[i][j]=='#'?0:map[i][j]-'A'+1;        Q[tail].time=0;        state[i][j][Q[tail].nTNT]=0;            //错误1 这里漏了        tail++;    }    while(front<tail)    {        for(int d=0;d<4;d++)        {            int nr=Q[front].r+dr[d];            int nc=Q[front].c+dc[d];            int nTNT=Q[front].nTNT;            int time=Q[front].time;            if(nr>=1&&nr<=R-1&&nc>=1&&nc<=C-1&&map[nr][nc]!='*')            {                if(map[nr][nc]=='.' && check(nr,nc,nTNT,time))                {                    state[nr][nc][nTNT]=time;                    Q[tail]=node(nr,nc,nTNT,time);                    tail++;//也可以这么写进行剪枝 if(que[tail].time<ans) tail++;                }                else if(isdigit(map[nr][nc]))//数字墙                {                    if(nTNT>0 && check(nr,nc,nTNT-1,time))//炸开                    {                        state[nr][nc][nTNT-1]=time;                        Q[tail]=node(nr,nc,nTNT-1,time);                        tail++;//也可以这么写进行剪枝 if(que[tail].time<ans) tail++;                    }                    if(check(nr,nc,nTNT,time+map[nr][nc]-'0'))//花时间打开                    {                        state[nr][nc][nTNT]=time+map[nr][nc]-'0';                        Q[tail]=node(nr,nc,nTNT,time+map[nr][nc]-'0');                        tail++;//也可以这么写进行剪枝 if(que[tail].time<ans) tail++;                    }                }                else if(map[nr][nc]=='$')                {                    if(ans>time) ans=time;                }            }        }        front++;    }    return ans;}int main(){    while(true)    {        R=C=0;               //错误2,这句话之前写在了while(gets(map[0])) 的上面        while(gets(map[R]))        {            if(strlen(map[R]) == 0 ) break;            if(map[R][0]=='-') return 0;            R++;        }        C=strlen(map[0]);        int ans=BFS();        if(ans==1000000) printf("IMPOSSIBLE\n");        else printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击