Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 8804 | Accepted: 2069 |
Description
Input
Output
Sample Input
8 9 1 1 1 3 2 1 1 3 3 1 1 3 4 1 1 3 1 1 0 3 1 2 0 3 1 3 0 3 1 4 0 3 2 1 1 2 2 1 2 3 1 3 1 1 3 2 1 3 3 1 1 2 0 3 3 0 4 3 1 1.5 1.5 4 0 1 1 0 1 1 1 1 1 2 1 1 1 1 2 0 1 1.5 1.7 -1 -1
Sample Output
5 -1
第一次碰到网格的题,搜了一下方法,最后总结出一个比较简单好理解的算法。
主要问题就是怎么把网格转化成二维图。
在这里我们把每个网格的左下角的点作为网格的坐标,用两个数组h和l来分别记录这个网格的下边和左边的权值,我们把墙的权值设为inf,门的权值为1,初始化为0,这样我们在读入数据的时后就把图建好。
搜索:利用广度优先搜索,这里有个坑点就是这货有可能根本就没在迷宫里面,这时候肯定穿过的门是0了。
在这里我们要好好考虑一下,首先就是状态,对于每一个网格我们可以走4个方向,首先就是墙我们是不能撞的,在这里,我们可以增加一个记录每一个点的权值和的数组,
初始化为inf。这样,我们只走能使得走入的下一个点的和变得更少的点,也就是满足dis[新点]>dis[旧点]+串xx的权值,我们才把这个新点入队。
并且这样还可以确保走过的点不会再走回去。
这时候我们就要避免一个问题,我们不可能一直在迷宫外面一直搜索下去,所以我们要设置一个边界,这个边界就是迷宫的大小(外面一层的点的坐标的最大值),注意这个地方不是网格的点的坐标的最大值,因为如果这样的话你看看示例就知道了,所以,我们要在迷宫外面多设一层网格,也就是迷宫外面一层的点的坐标的最大值。
同时我们还要考虑一个问题,那就是这不同与点的bfs,不同于往常,原因就是在一个网格里,它除了墙和门之外还有可能是什么都没有的!!
这样的话我们上下左右4个方向走完,压进队列的值,此时的状态并不一定是相同的,如果按照普通的搜索,每走一步步数必定加一,但这个就不同了,虽然我们不会去撞墙(因为墙的权值为inf,再加上自己(大于等于0))必定不会比新点(初始化为inf)小,但是因为并不是只有门的存在,所以,我们走一步之后可能步数并没有加一。
我用红色代表什么也没有,灰色代表门,那么先进入队列的是上面2号格子此时步数是要加一的,而后进队列的就是1号个子但是它此时的步数不需要加1,所以说如果照普通的搜索你搜索出来的就不一定是步数也就是穿过的门数最少的了。
我们的解决方法就是我们这次不用普通的队列而是优先队列,权值越小优先级越高,这样就解决了这个问题。
贴上代码:
#include
#include
#include
#include
#include
using namespace std;
const int inf=0x3f3f3f;
const int N=250;
struct node
{
int x,y,door;
//步数少的优先
bool operator<(const node &a)const
{
return a.doorq;
for(i=0;i<=maxx;++i)
for(j=0;j<=maxy;++j)dis[i][j]=inf;//初始化
node k;
k.x=0;k.y=0;k.door=0;//从他爸的地方为起始点
dis[0][0]=0;
q.push(k);
while(!q.empty())
{
k=q.top();
q.pop();
if(k.x==sx&&k.y==sy)return ;//找到了就返回
int x=k.x, y=k.y;
//向上走
if(y+1<=maxy&&dis[x][y+1]>dis[x][y]+h[x][y+1])
{
dis[x][y+1]=dis[x][y]+h[x][y+1];//上面那面xx就是上个格子的下面xx
k.x=x;
k.y=y+1;
k.door=dis[x][y+1];
q.push(k);
}
//向下走
if(y-1>=0&&dis[x][y-1]>dis[x][y]+h[x][y])
{
dis[x][y-1]=dis[x][y]+h[x][y];
k.x=x;
k.y=y-1;
k.door=dis[x][y-1];
q.push(k);
}
//向右走
if(x+1<=maxx&&dis[x+1][y]>dis[x][y]+l[x+1][y])
{
dis[x+1][y]=dis[x][y]+l[x+1][y];
k.x=x+1;
k.y=y;
k.door=dis[x+1][y];
q.push(k);
}
//向左走
if(x-1>=0&&dis[x-1][y]>dis[x][y]+l[x][y])
{
dis[x-1][y]=dis[x][y]+l[x][y];
k.x=x-1;
k.y=y;
k.door=dis[x-1][y];
q.push(k);
}
}
dis[sx][sy]=-1;
}
int main()
{
int x,y,d,t;
int i;
while(~scanf("%d%d",&n,&m))
{
if(n==-1&&m==-1)break;
//你要知道并不是迷宫里面除了墙就是门的,可以什么都没有的,直接就穿过去了
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
maxy=-1;maxx=-1;
while(n--)
{
scanf("%d%d%d%d",&x,&y,&d,&t);
if(d)
{
for(i=0;i=maxx||f2>=maxy)
{
printf("0\n");
continue;
}
sx=f1;
sy=f2;
bfs();
printf("%d\n",dis[sx][sy]);
}
return 0;
}