逃离迷宫 HDU

来源:互联网 发布:如何组织js代码 编辑:程序博客网 时间:2024/06/04 08:23

传送门


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

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


AC代码:

#include <iostream>#include <cstdio>#include <stack>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<NOD> 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;}


原创粉丝点击