Abbott‘s Revenge UVA - 816

题目链接:Abbott's Revenge - UVA 816 - Virtual Judge (vjudge.net)

这个题,说时候,个人感觉没学过算法的,你就算看着题解也是云里雾里的,像我这种就得看着刘汝佳老师的解题思路,自己还要参考别人的代码,好歹最后自己搞出来了,所以说考试的时候遇到这个题咋办?(这题真的是比较有难度,我写了一个下午,直接寄掉......)

AC代码:(仅供参考)题解思路均在代码注释中

#include <iostream>
#include <vector>
#include <string.h>
#include <queue>//注意用万能头文件时会出现定义全局变量报错的问题,万能头文件要慎用!!!
using namespace std;
const char *dirs = "NESW";
const char *turns = "FLR";
const int dx[]={-1,0,1,0};
const int dy[]={0,1,0,-1};//注意这个地方要对应好方向,比如N对应-1的dx和0的dy
int x0,y0,x1,y1,drip,xend,yend;
bool can_turn[12][12][4][3];//定义的是一个方向许可四维数组,第三个下标是表示面朝的方向,第四个下标是三个方向许可(左右上)
int d[12][12][4];
char ch;
string name;
int dir_id(char c){return (strchr(dirs,c)-dirs);}//这两个函数可以将字符表示的方向转换为int化为x,y方向方便计算
int turn_id(char c){return (strchr(turns,c)-turns);}
bool in(int r,int c)
{
    return (r>=1&&r<=9&&c>=1&&c<=9);//判断是否出界
}

class node{
public:
    int x,y,dir;
    node(int x=0,int y=0,int dir=0):x(x),y(y),dir(dir){}//默认值为零一定要写,因为后面定义以类成员为元素的数组需要用到无参构造函数

};
node p[12][12][4];
vector<node> anss;//用于存储过程节点
node walk(const node&u,int turn)
{
    int d=u.dir;//turn等于零的时候
    if(turn==1)
        d=(u.dir+3)%4;//相当于原来的方向左转,因为受来时方向的影响(例如北来西去)
    if(turn==2)
        d=(u.dir+1)%4;//同上
    return node(u.x+dx[d],u.y+dy[d],d);
}
bool read()
{
    memset(can_turn, 0, sizeof(can_turn));
    cin>>name;
    if(name=="END")
        return false;
    cin>>x0>>y0>>ch>>xend>>yend;
    x1=x0+dx[dir_id(ch)];//注意看好要加谁,因为dir_id函数也返回int,但是意义不同,dir_id返回的是字符对应位置,还应转换到x和y坐标代入计算
    y1=y0+dy[dir_id(ch)];
    drip=dir_id(ch);
    int r,c;
    vector<string> t;
    while(cin>>r&&r!=0)
    {
        cin>>c;
        string s;
        while(cin>>s&&s!="*")
        {
            for(int i=1;i<s.length();++i)//s[0]是进入时的面朝方向
            {
                can_turn[r][c][dir_id(s[0])][turn_id(s[i])]=1;
            }
        }
    }
    return true;
}
void print(node u)
{
    anss.clear();
    while(1)//这个是从尾结点开始检测,每一个p是他上一个节点
    {
        anss.push_back(u);
        if(d[u.x][u.y][u.dir]<0) break;
        u=p[u.x][u.y][u.dir];
    }
    anss.push_back(node(x0,y0,drip));//因为第个节点对应的p没有头结点(x0)所以在后面要填上x0
    cout<<name<<endl;
    cout<<" ";
    int cnt=0;
    for(int i=anss.size()-1;i>=0;--i)//倒着输出
    {
        if(cnt%10==0&&cnt!=0) cout<<endl<<" ";
        cnt++;
        cout<<" "<<"("<<anss[i].x<<","<<anss[i].y<<")";
    }
    cout<<endl;

}
void bfs()
{
    memset(d,-1,sizeof(d));
    queue<node> q;
    node a;
    a.x=x1;
    a.y=y1;
    a.dir=drip;
    q.push(a);
    while(!q.empty())
    {
        node st=q.front();
        if(st.x==xend&&st.y==yend)
           {
               print(st);
               return ;
           }
        q.pop();
        for(int i=0;i<3;i++)
        {
            node h=walk(st,i);//进行一步走
            if(can_turn[st.x][st.y][st.dir][i]&&in(h.x,h.y)&&d[h.x][h.y][h.dir]<0)//判断该处可以走
            {
                d[h.x][h.y][h.dir]=d[st.x][st.y][st.dir]+1;//最后这一块应该是比较好理解了
                p[h.x][h.y][h.dir]=st;
                q.push(h);
            }
        }

    }
    cout<<name<<endl<<"  No Solution Possible"<<endl;

}

int main()
{
    while(read())
        bfs();
    return 0;
}
 

                                                                                               算法虐我千百遍,我待算法如~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值