水管工游戏(啊哈算法)

 

    一块矩形土地被分成 N*M 的单位正方形,现在这块土地已经埋有一些水管,水管将从坐标为 (1,1)的红矩形土地的左上角
    左部边缘,延伸到坐标为(N,M)的矩形土地的右下角右部边缘。水管只有两种,弯管或者直管;
    弯管表示为1到4,直管表示为5,6,树木为0;

    请编写程序判断该地图是否能得到合理的水管路线;如果能,打印出路径;如果不能,输出impossible。

    分析:既然,弯管与直管可以通过变换摆放方式来调整方向,那么我们必定要将(x,y)的进水口方向找到。
    不妨设左,上,右,下的方向分别为 1,2,3,4;

/**
    一块矩形土地被分成 N*M 的单位正方形,现在这块土地已经埋有一些水管,水管将从坐标为 (1,1)的红矩形土地的左上角
    左部边缘,延伸到坐标为(N,M)的矩形土地的右下角右部边缘。水管只有两种,弯管或者直管;
    弯管表示为1到4,直管表示为5,6,树木为0;

    请编写程序判断该地图是否能得到合理的水管路线;如果能,打印出路径;如果不能,输出impossible。

    分析:既然,弯管与直管可以通过变换摆放方式来调整方向,那么我们必定要将(x,y)的进水口方向找到。
    不妨设左,上,右,下的方向分别为 1,2,3,4;
*/

/**
    data:
    5 4
    5 3 5 3
    1 5 3 0
    2 3 5 1
    6 1 1 5
    1 5 5 4
*/

#include <iostream>
#include <queue>
#include <stack>

using namespace std;

const int maxn  = 510;
int e[maxn][maxn];
bool hs[maxn][maxn];
int n,m;

int flag = 0;
typedef pair<int,int> PII;
queue<PII> q;
stack<PII> s;
PII stk[maxn];
int top = 0;

void dfs(int x,int y,int fron)
{
    if(x == n && y == m+1)
    {
        flag = 1;
        ///错误路径,路径应该用栈来存储,用队列来存储的话,每次删除应该是队尾元素,
        ///但是队列就会删除队头元素(因为队列是先进先出,每次都是把先进去的元素给删除了
        while(q.size())
        {
            PII t = q.front();
            q.pop();
            cout << t.first << ' ' << t.second << endl;
        }

        ///用栈存储正确路径
        puts("--------------");
        for(int i=1;i<=top;++i)
            cout << stk[i].first << ' ' << stk[i].second << endl;

        ///STL实现的容器栈只能逆序输出;
        puts("************");
        while(s.size())
        {
            PII t = s.top();
            s.pop();
            cout << t.first << ' ' << t.second << endl;
        }
        return ;
    }
    if(x<1 || x>n || y<1 || y>m)
        return;
    if(hs[x][y])
        return;

    hs[x][y] = 1;
    q.push({x,y});
    stk[++top] = {x,y};
    s.push({x,y});

    if(e[x][y] >= 5 && e[x][y] <= 6)    ///直管
    {
        if(fron == 1)
            dfs(x,y+1,1);
        else if(fron == 2)
            dfs(x+1,y,2);
        else if(fron == 3)
            dfs(x,y-1,3);
        else
            dfs(x-1,y,4);
    }
    else if(e[x][y] >=1 && e[x][y] <= 4)    ///弯管
    {
        if(fron == 1)
        {
            dfs(x-1,y,4);
            dfs(x+1,y,2);
        }
        else if(fron == 2)
        {
            dfs(x,y-1,3);
            dfs(x,y+1,1);
        }
        else if(fron == 3)
        {
            dfs(x-1,y,4);
            dfs(x+1,y,2);
        }
        else
        {
            dfs(x,y-1,3);
            dfs(x,y+1,1);
        }
    }

    hs[x][y] = 0;   ///回溯
    if(q.size())
        q.pop();
     -- top;    ///将(x,y)出栈
     s.pop();
}


int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            cin >> e[i][j];

    dfs(1,1,1);
    if(flag == 0)
        puts("impossible");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值