POJ3083 Children of the Candy Corn DFS+BFS

这道题最坑的一点是,,G++一直WA,但是C++过了。。。。。EXM?????

一开始我以为可能有不记录方向的方法,但网上一搜发现,,算了还是慢慢做吧。。比较巧妙的是:

1. 把方向用数字表示,避免了字符串后续很烦的操作。

2. DFS时不能用vis数组,用break保证了每步只走一种情况并且不会陷入死循环。

附上AC代码(又丑又长QAQ):

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int>pp;
#define mkp make_pair

const int MAX=45;
int n,m;//行,列
char s[MAX][MAX];
int ans1,ans2,ans3;
pp st,en;//起点,终点
/*      0(上)
   1(左)     2(右)
        3(下)       */
int dx[4]={-1,0,0,1};//0123
int dy[4]={0,-1,1,0};//上左右下
map<int,string>mpl,mpr;//左右优先的顺序
void init()
{   //当前方向,方向顺序
    mpl[0]="1023";mpr[0]="2013";
    mpl[3]="2310";mpr[3]="1320";
    mpl[1]="3102";mpr[1]="0132";
    mpl[2]="0231";mpr[2]="3201";
}

void dfs(int k,int sign,pp p,int step)
{   //sign==1:左  sign==2:右
    int x=p.first,y=p.second;
    if(s[x][y]=='E')
    {
        if(sign==1) ans1=step;
        else ans2=step;
        return;
    }
    string ord;//行走顺序
    if(sign==1) ord=mpl[k];
    else ord=mpr[k];
    for(int i=0;i<4;i++)
    {
        int ii=ord[i]-'0';
        int xx=x+dx[ii],yy=y+dy[ii];
        if(xx>=0&&yy>=0&&xx<n&&yy<m&&s[xx][yy]!='#')
        {
            dfs(ii,sign,mkp(xx,yy),step+1);
            break;//巧妙!这样一次一定只走一种情况!!同时不用标记vis!!
        }
    }
}

int vis[MAX][MAX];
int bfs()
{
    memset(vis,0,sizeof(vis));
    queue<pp>que;
    que.push(st);
    vis[st.first][st.second]=1;
    while(!que.empty())
    {
        pp k=que.front();que.pop();
        int x=k.first,y=k.second;
        if(s[x][y]=='E')
        {
            return vis[x][y];
        }
        for(int i=0;i<4;i++)
        {
            int xx=x+dx[i],yy=y+dy[i];
            if(xx>=0&&yy>=0&&xx<n&&yy<m&&!vis[xx][yy]&&s[xx][yy]!='#')
            {                            //注意写"!="而不是"=="!!(否则忽略'E'!)
                vis[xx][yy]=vis[x][y]+1;
                que.push(mkp(xx,yy));
            }
        }
    }
}
int main()
{
    init(); int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        for(int i=0;i<n;i++)
            scanf("%s",s[i]);
        bool sign=false;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(s[i][j]=='S') st.first=i,st.second=j;
                //else if(s[i][j]=='E') en.first=i,en.second=j;
        if(st.first==0)//顶端向下
            dfs(3,1,st,1),dfs(3,2,st,1);
        else if(st.first==n-1)//底端向上
            dfs(0,1,st,1),dfs(0,2,st,1);
        else if(st.second==0)//左侧向右
            dfs(2,1,st,1),dfs(2,2,st,1);
        else if(st.second==m-1)//右侧向左
            dfs(1,1,st,1),dfs(1,2,st,1);
        ans3=bfs();
        printf("%d %d %d\n",ans1,ans2,ans3);
    }
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值