TOJ 3709: Number Maze

描述

You are playing one game called "Number Maze". The map of an example is shown in the following figure.


In the map, there are N*N+2 cells. When the game starts, you stay the top-left cell and you target is to reach the bottom-right cell with fewest number of moves. At the first step, you must move to the right of the start cell. After that, you can move to any cell (left, right, up or down, but can not move diagonally) if the target cell can be divided by the sum of the previous two numbers. However, you should never move backwards. For example, at first, you stay at the "2" cell, and you must move to the "6" cell, then have two selections "8" or "4" because (2+6)/8=1 and (2+6)/4=2, you can not move back to the "2" cell at this step although (2+6)/2=4. One possilbe solution is 2->6->8->7->5->3->4->7->11->2->13, and the total number of moves is 10.
Another solution is also legal but has longer moves:
2->6->8->7->5->3->4->7->5->3->4->7->11->2->13

输入

Thare are at most 20 cases. The first line of each case has three integers N<=10, S and T, which N indicates the dimension of the map, S and T indicate the number in the start and target cell. Then follows N lines and each line has N positive integers which indicate each number in the N*N cells.
There has one blank line after each case and you can assume that the total number of all cells is no larger than 1000000.

The inputs are ended with End of File. If you have some questions, please visit the help page.

输出

Each case outputs the fewest number of moves or "Impossible" if you can not reach the target cell per line. 

样例输入

3 2 13
6 4 3
8 7 5
2 11 2

样例输出

10

解题思路: 一道广搜的题目, 但是由于一个点可以进队列很多次,会导致MLE, 我们需要控制点的进队列次数,这里就用一个vis数组判断好了。

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,s,t,flag,ex,ey;
struct node{
int x,y,dir,num,first,second;   //first存放前面的第一个数, second存放前面的第二个数
}k,p,q;
int a[15][15];
int dir[6][2]={0,0,-1,0,1,0,0,-1,0,1};
void bfs()
{
    k.x=1;
    k.y=1;
    k.dir=4;       //初始状态方向向右
    k.num=1;
    k.first=s;
    k.second=a[1][1];
    queue <node> qu;
    int vis[15][15]={0};  //判断每个点的进队列次数
    qu.push(k);
    while(!qu.empty())
    {
        k=qu.front(); qu.pop();
        if(k.x==ex&&k.y==ey)
        {
            flag=1;
            cout<<k.num<<endl;
            break;
        }
        for(int i=1;i<=4;i++)
        {
            p.x=k.x+dir[i][0];
            p.y=k.y+dir[i][1];
            p.num=k.num+1;
            if(i==1&&k.dir==2||i==2&&k.dir==1||i==3&&k.dir==4||i==4&&k.dir==3) continue;  //如果与初始方向相反的话,会回到上一个点,直接跳出
            if(p.x==ex&&p.y==ey||(p.x>=1&&p.x<=n&&p.y>=1&&p.y<=n))
            {
                p.dir=i;
                vis[p.x][p.y]++;
                if((k.first+k.second)%a[p.x][p.y]==0&&vis[p.x][p.y]<=100)
                {
                    p.first=k.second;
                    p.second=a[p.x][p.y];
                    qu.push(p);
                }
            }
        }
        if(flag==1) break;
    }
}
int main()
{
    int m,i,j;
    ios::sync_with_stdio(false);
    while(cin>>n>>s>>t)
    {
        flag=0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++) cin>>a[i][j];
        }
        ex=n;
        ey=n+1;
        if(n==0)
        {
            cout<<"1\n";
            continue;
        }
        a[n][n+1]=t;
        bfs();
        if(flag==0) cout<<"Impossible\n";
    }
}

猜你喜欢

转载自www.cnblogs.com/ww123/p/9022275.html