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.

输出

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



先解释下题意:给你应该N*N的矩阵。矩阵的每个位置都有值,然后在矩阵的左上和右下都有一个位置。叫我们找一条走的步数最小的路可以从左上走到右下。

可以上下左右走。。。但是每次不可以往回走。都是下一步要走的位置的值要可以被你所在位置和上个位置的值的和整除。

有二个坑点。。。不能往回走。和可能会产生回路。

下面是代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
int MAP[20][20];
struct A
{
int x,y,side;
int fan,z1,z2;
bool  operator ==(const A &a)
{
return ((a.x==x)&&(a.y==y)&&(a.side==side)&&(a.fan==fan)&&(a.z1==z1)&&(a.z2==z2));
}
};


int N,S,T;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int bfs()
{
queue<A>Q;
A M[110];//用于判断是不是产生了回路。 
int len=0;
A d;
d.x=1;
d.y=1;
d.fan=0;
d.side=1;
d.z1=S;
d.z2=MAP[1][1];
Q.push(d);
while(!Q.empty())
{
d=Q.front();
Q.pop();
bool f=0;
for(int i=0;i<len;i++)
if(M[i]==d)
{
f=1;break;
}
if(f)continue;
else 
{
M[len++]=d;
}
if(d.x==N&&d.y==N+1)return d.side;
for(int i=0;i<4;i++)
{
A D=d;
D.x+=dir[i][0];
D.y+=dir[i][1];
if(D.x>=1&&D.x<=N&&D.y>=1&&d.y<=N+1)
{
if(D.y==N+1&&D.x!=N)continue;
if((D.z1+D.z2)%MAP[D.x][D.y]!=0)continue;//保证整除 
if((D.fan+2)%4==i)continue;//保证不往回走 
// printf("%d %d %d %d %d++++\n",D.x,D.y,D.fan,D.z1,D.z2);
D.z1=D.z2;
D.fan=i;
D.z2=MAP[D.x][D.y];
D.side++;
Q.push(D);
}
}
}
return -1;
}
int main()
{
while(scanf("%d",&N)!=EOF)
{
scanf("%d %d",&S,&T);
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
scanf("%d",&MAP[i][j]);
}
MAP[1][0]=S;
MAP[N][N+1]=T;
int ans=bfs();
if(ans==-1)puts("Impossible");
else printf("%d\n",ans);
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wumingiswu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值