逃离迷宫 HDU - 1728 深度优先搜索

传送门


解题思路:既然找转向次数最少,没有限制移动几步,只要能到达终点即可,因此选择深度优先搜索,并且剪枝, 只要转向次数超过了k那就不再继续,这样只要到达终点就是答案。

但是还有个问题就是,每个方向走的时候怎么知道需不需要转向次数加一, 只需要加一个标记即可, 标记记录当前的方向, 如果下次走的方向跟现在相同就不加, 不同就加一。  表达式(nod.turn != i) 返回值为逻辑真假, 即0或1.


AC代码:

#include 
#include 
#include 

using namespace std;

struct NOD
{
    int x, y;
    int turn;
}nod;
int n, m, x1, y1, x2, y2, k;
int dx[] = {0,0,1,-1}, dy[] = {1,-1,0,0};
int turn[105][105];
char mp[105][105];
stack st;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        while(!st.empty()) st.pop();   //清空栈
        for(int i=0; i<105; ++i)
            for(int j=0; j<105; ++j) turn[i][j] = 100;//初始化数组
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; ++i) scanf("%s", mp[i]+1);
        scanf("%d%d%d%d%d", &k, &y1, &x1, &y2, &x2);//题目先输入的列, 所以先y后x  转换成x代表行, y代表列
        turn[x1][y1] = -1;//由于一开始是不计方向的所以是-1
        int ok = 0;
        for(st.push((NOD){x1, y1, -1}); !st.empty();)
        {
            nod = st.top();
            st.pop();
            //printf("~x = %d y = %d\n", nod.x, nod.y);
            if(turn[nod.x][nod.y] > k) continue;//此时转向次数已经超过k, 不符合条件, 剪枝掉
            if(nod.x == x2 && nod.y == y2)//找到终点
            {
                ok = 1;
                break;
            }
            for(int i= 0; i<4; i++)//找四个的方向
            {
                int xx = nod.x + dx[i];
                int yy = nod.y + dy[i];
                if(xx > 0 && yy > 0 && xx <= n && yy <= m && mp[xx][yy] != '*' && turn[xx][yy] >= turn[nod.x][nod.y] + (nod.turn != i))//!=i的意思是说如果方向不同就加一
                {
                    turn[xx][yy] = turn[nod.x][nod.y]+(nod.turn != i);
                    st.push((NOD){xx, yy, i});
                }
            }
        }
        if(ok) puts("yes");
        else puts("no");
    }
    return 0;
}


你可能感兴趣的:(算法基础----DFS)