UVA816Abbott的复仇

其实这道题就是一个带有方向的bfs,只要在普通的数组后面加上一个方向即可bfs然后AC

注意点:如果一个点重复以同一个方向进入就得跳过这个点(我因为这个一直卡着)

一个点有可能重复访问,因为方向不一样,所以要在vis数组也加一个方向

输出格式很重要,每10个换一行,而且要在前面加两个空格

每次进入一个点后要考虑能走的方向,可以编写函数来转换成东南西北

下面是AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
int headx,heady,tarx,tary;
int dx[]= {-1,0,0,1};
int dy[]= {0,-1,1,0};
int vis[200][200][200];//记录访问状态
vector<int>chess[100][100][10];//记录迷宫的x,y,进入方向,能走的方向
string a;
struct node//记录答案的node
{
    int x;
    int y;
    node(int x,int y):x(x),y(y) {}
};
struct pos//每个点的结构体
{
    int x;
    int y;
    int d;
    vector<node>way;//记录这个点走的路径
    pos(int x,int y,int d):x(x),y(y),d(d) {}
};
vector<node>ans;//记录答案
int ex(char a)//将字母转换成数字
{
    if(a=='N')
        return 1;
    else if(a=='S')
        return 4;
    else if(a=='W')
        return 2;
    else if(a=='E')
        return 3;
}
int dir(char in,char can)//将进入方向和能走的方向转换成整体的东南西北方向
{
    if(can=='F')return ex(in);
    else if(can=='L')
    {
        if(in=='N')
            return 2;
        else if(in=='S')
            return 3;
        else if(in=='W')
            return 4;
        else if(in=='E')
            return 1;
    }
    else
    {
        if(in=='N')
            return 3;
        else if(in=='S')
            return 2;
        else if(in=='W')
            return 1;
        else if(in=='E')
            return 4;
    }
}
bool solve()
{
    string d;
    int x,y;
    ans.clear();//初始化
    memset(vis,0,sizeof(vis));
for(int i=0;i<10;i++)
{
    for(int j=0;j<10;j++)
    {
        for(int k=0;k<6;k++)
            chess[i][j][k].clear();
    }
}
    cin>>headx>>heady>>d>>tarx>>tary;//存储起点终点
    string di;
    while(cin>>x)
    {
        if(x==0)break;//输入结束
        cin>>y;
        while(cin>>di)//存储方向
        {
            if(di=="*")break;
            for(int i=1; i<di.length(); i++)
            {
                chess[x][y][ex(di[0])].push_back(dir(di[0],di[i]));
            }
        }
    }
   queue<pos>q;
   pos k=pos(headx+dx[ex(d[0])-1],heady+dy[ex(d[0])-1],ex(d[0]));//起点走出的第一个点
   k.way.push_back(node(headx,heady));
    q.push(k);
    while(!q.empty())
    {
        pos t=q.front();
        q.pop();if(vis[t.x][t.y][t.d])continue;//如果走入循环就跳过
        vis[t.x][t.y][t.d]=1;//标记已经走过的状态
        t.way.push_back(node(t.x,t.y));//记录路径
        if(t.x==tarx&&t.y==tary)//到终点处理
        {
            ans=t.way;
            return true;
        }
        x=t.x;
        y=t.y;
        for(int j=0; j<chess[x][y][t.d].size(); j++)//遍历能走的方向
        {
            int xx,yy,dd;
            xx=x+dx[chess[x][y][t.d][j]-1];
            yy=y+dy[chess[x][y][t.d][j]-1];
            dd=chess[x][y][t.d][j];
                pos te=t;
                te.x=xx;
                te.y=yy;
                te.d=dd;
                q.push(te);
        }
    }return false;
}
void show()
{
    for(int i=0;i<ans.size();i++)
    {
        if((i+1)%10!=1)cout<<" ";//非开头
        else cout<<"  ";//开头
        printf("(%d,%d)",ans[i].x,ans[i].y);
        if((i+1)%10==0&&(i+1)!=ans.size())cout<<endl;//防止长度刚好是10的倍数导致换行两次
    }cout<<endl;
}
int main()
{
    //freopen("1.txt","w",stdout);
    string name;
    while(cin>>name)
    {
        if(name=="END")break;
        cout<<name<<endl;
        if(solve())show();
        else cout<<"  No Solution Possible\n";
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值