2014 UESTC Training for Search Algorithm H

还是bfs解迷宫问题,这里的方式是加入了左转右转来控制方向,每次前进格数是1-3格
于是节点状态定义还要加入一个方向变量,这里0,1,2,3分别表示上右下左。同事判重vis也要三维vis[55][55][4];
另外还需要注意的是图内障碍物与通路的坐标与图中点坐标的对应性,1,0与坐标(交叉点)坐标并不是相同的
再判断是否能前移的时候要注意如果再路径中走1步就遇到障碍物是那么这条路径就更不能走2步三步,发生了截止,下面这里判断的方式
int dn[]={-1,0,1,0};
int dm[]={0,1,0,-1};
for (int j=1;j<=3;j++)
            {
                int nn=u.n+dn[i]*j;
                int nm=u.m+dm[i]*j;
                if (!judge(nn,nm)) break;for (int j=1;j<=3;j++)
//这里这么判断
judge函数
bool judge(int n,int m)
{
    if (n<1 || n>N-1 || m<1 || m>M-1) return false;
    if (G[n-1][m-1] || G[n-1][m] || G[n][m-1] || G[n][m]) return false;
    return true;
}

其余只需要不停判断加入队列找到答案就可以。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
	return a % b == 0 ? b : gcd(b, a % b);
}
//注意每一次可以走1,2,3格
int dn[]={-1,0,1,0};
int dm[]={0,1,0,-1};
struct node
{
    int n,m;
    int time;
    int dir;//朝向0,1,2,3;上右下左
}q[25500];
int s_n,s_m;
int end_n,end_m;
int Dir;
int N,M;
int G[55][55];
int vis[55][55][4];
int ans;
void show()
{
    for (int i=0;i<N;i++)
    {
        for (int j=0;j<M;j++)
            printf("%d",G[i][j]);
        putchar('\n');
    }
}
bool judge(int n,int m)
{
    if (n<1 || n>N-1 || m<1 || m>M-1) return false;
    if (G[n-1][m-1] || G[n-1][m] || G[n][m-1] || G[n][m]) return false;
    return true;
}
void read()
{
    memset(G,0,sizeof(G));
    for (int i=0;i<N;i++)
        for (int j=0;j<M;j++)
        scanf("%d",&G[i][j]);
    scanf("%d%d%d%d%d",&s_n,&s_m,&end_n,&end_m,&Dir);
    //show();
}
void bfs()
{
    memset(vis,0,sizeof(vis));
    q[0].dir=Dir;q[0].time=0;
    q[0].m=s_m;q[0].n=s_n;
    int front=0,rear=1;
    vis[s_n][s_m][Dir]=1;
    node u,s;
    while (front<rear)
    {
         u=q[front];
        if (u.m==end_m && u.n==end_n)
        {
            ans=u.time;
            return ;
        }
        if (u.dir==0)//上
        {
            for (int j=1;j<=3;j++)
            {
                int nn=u.n+dn[0]*j;
                int nm=u.m+dm[0]*j;
                if (!judge(nn,nm)) break;
                if ( judge(nn,nm) && !vis[nn][nm][0])
                {
                    s.n=nn;s.m=nm;s.time=u.time+1;
                    s.dir=0;
                    vis[nn][nm][0]=1;
                    q[rear++]=s;
                }
            }
        }
        if (u.dir==1)//右
        {
            for (int j=1;j<=3;j++)
            {
                int nn=u.n+dn[1]*j;
                int nm=u.m+dm[1]*j;
                if (!judge(nn,nm)) break;
                if (judge(nn,nm) &&!vis[nn][nm][1])
                {
                    s.n=nn;s.m=nm;s.time=u.time+1;
                    s.dir=1;
                    vis[nn][nm][1]=1;
                    q[rear++]=s;
                }
            }
        }
        if (u.dir==2)//下
        {
            for (int j=1;j<=3;j++)
            {
                int nn=u.n+dn[2]*j;
                int nm=u.m+dm[2]*j;
                if (!judge(nn,nm)) break;
                if (judge(nn,nm) &&!vis[nn][nm][2])
                {
                    s.n=nn;s.m=nm;s.time=u.time+1;
                    s.dir=2;
                    vis[nn][nm][2]=1;
                    q[rear++]=s;
                }
            }
        }
        if (u.dir==3)//左
        {
            for (int j=1;j<=3;j++)
            {
                int nn=u.n+dn[3]*j;
                int nm=u.m+dm[3]*j;
                if (!judge(nn,nm)) break;
                if (judge(nn,nm) &&!vis[nn][nm][3])
                {
                    s.n=nn;s.m=nm;s.time=u.time+1;
                    s.dir=3;
                    q[rear++]=s;
                    vis[nn][nm][3]=1;
                }
            }
        }


        if (u.dir==0 || u.dir==2)
        {
              if (!vis[u.n][u.m][1])
              {
                  s.m=u.m;s.n=u.n;s.time=u.time+1;
                  s.dir=1;
                  vis[u.n][u.m][1]=1;
                  q[rear++]=s;
              }
              if (!vis[u.n][u.m][3])
              {
                  s.m=u.m;s.n=u.n;s.time=u.time+1;
                  s.dir=3;
                  vis[u.n][u.m][3]=1;
                  q[rear++]=s;
              }
        }
         if (u.dir==1 || u.dir==3)
        {
              if (!vis[u.n][u.m][0])
              {
                  s.m=u.m;s.n=u.n;s.time=u.time+1;
                  s.dir=0;
                  vis[u.n][u.m][0]=1;
                  q[rear++]=s;
              }
              if ( !vis[u.n][u.m][2])
              {
                  s.m=u.m;s.n=u.n;s.time=u.time+1;
                  s.dir=2;
                  vis[u.n][u.m][2]=1;
                  q[rear++]=s;
              }
        }
       front++;
    }
}
int main()
{
    //freopen("sample.txt","r",stdin);
    while (scanf("%d%d",&N,&M)==2)
    {
        if (N==0 && M==0) break;
        read();
        ans=-1;
        bfs();
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值