Exercise(17):装水管

/*
        让我们一起装水管吧!
    问题描述:
    一块矩形土地被分为N*M的单位正方形,现在土地上已经设有一些水管,
    水管将从坐标为(1,1)的矩形土地左上角左部边缘,延伸到坐标为(N,M)的
    矩形土地的右下角右部边缘,(即左上角的单位正方形的左边为进水口,右下角的单位正方形的右边为出水口)。水管只有两种 L型和I型水管。每种管道将占据一个单位正方形土地。你现在可以旋转这些管道,使其构成一个管道系统,即创造出一条从
    (1,1)到(N*M)的连通管道。注意,这块矩形土地内可能会有树木阻挡你放置管道。
    L型水管有4种放置方法, I型水管有两种放置方法.
    分别表示如下:
    ^   —> <—   ^ ^ 
    |   |     |   | | < —>  树木用0表示
    —> v     v <— v

     1   2   3   4  5   6
    输入描述 InputDescription
        第一行输入两个整数N,M (0<N,M<=50),用空格分隔开。表示将土地划分为N*M个单   位正方形。
        剩下N行,每行有M个数,行内的数用空格隔开,行间要换行。表示各个单位
        正方形土地的情况(水管or树木)。

    输出描述 OutDescription
        输出水管的连通方式,格式为(i,j) (0<i<=50,0<j<=50)
        若无法形成一个连通系统则输出 impossible 。 

    样例输入 SampleInput
        5 4
        5 3 5 3
        1 5 3 0
        2 3 5 1
        6 1 1 5
        1 5 5 4
    样例输出 SampleOutput
        (1,1) (1,2) (2,2) (3,2) (3,3) (3,4) (4,4) (5,4)

*/
#include <iostream>
using namespace std;
int map[51][51];            // map 地图 
bool mark[51][51];          // 标记 
int n,m,top;                // n行 m列 top栈顶 
bool flag;                  // 判断是否存在可连通的系统 

typedef struct              // 用于储存结果 
{
    int x;                  // 横坐标 
    int y;                  // 纵坐标 
} no, nodeList[2501];       // 栈nodeList    
nodeList node;

// 广搜 
void DFS(int x,int y,int front)     // front为进水口 1,2,3,4分别表示左上右下 
{
    if(x==n && y==m+1)              // 判断是否找到出水口 
    {
        flag = true;                // 标记连通系统已完成 
        for(int i=1;i<=top;i++)     // 输出各管道路径 
            cout<<"("<<node[i].x<<","<<node[i].y<<")"<<ends;
        return;
    }

    if(x<1 || x>n || y<1 || y>m)    // 判断坐标是否越界 
        return;
    if(mark[x][y])                  // 判断该水管是否已被使用 
        return;

    mark[x][y] = true;              // 将该水管标记为已使用 
    node[++top].x = x;              // 将当前水管坐标存入栈 
    node[top].y = y;

    if(map[x][y]>=1 && map[x][y]<=4)        // L型水管有4种摆放方式(1~4) 
    {
        switch(front)
        {
            case 1:                         // 当进水口在左边 (L型水管对应的摆放方式有3、4)
                DFS(x+1,y,2);               // 方式3:向下搜,向下后进水口改为上 
                DFS(x-1,y,4);               // 方式4:向上搜,向上后进水口改为下 
                break;
            case 2:                         // 当进水口在上边 (L型水管对应的摆放方式有1、4)
                DFS(x,y+1,1);               // 方式1:向右搜,向右后进水口改为左 
                DFS(x,y-1,3);               // 方式4:向左搜,向左后进水口改为右                            
                break;
            case 3:                         // 当进水口在右边 (L型水管对应的摆放方式有1、2)
                DFS(x-1,y,4);               // 方式1:向上搜,向上后进水口改为下 
                DFS(x+1,y,2);               // 方式2:向下搜,向下后进水口改为上 
                break;
            case 4:                         // 当进水口在下边 (L型水管对应的摆放方式有2、3)
                DFS(x,y+1,1);               // 方式2:向右搜,向右后进水口改为左 
                DFS(x,y-1,3);               // 方式3:向左搜,向左后进水口改为右 
                break;              
        }
    }
    else if(map[x][y]>=5 && map[x][y]<=6)   // I型水管有2种摆放方式(5~6)
    {
        switch(front)
        {
            case 1:                         // 当进水口在左边 (I型水管对应的摆放方式有5)
                DFS(x,y+1,1);               // 方式5:向右搜,向右后进水口仍为左        
                break;
            case 2:                         // 当进水口在上边 (I型水管对应的摆放方式有6)
                DFS(x+1,y,2);               // 方式6:向下搜,向下后进水口仍为上 
                break;
            case 3:                         // 当进水口在右边 (I型水管对应的摆放方式有5)
                DFS(x,y-1,3);               // 方式5:向左搜,向左后进水口仍为右 
                break;
            case 4:                         // 当进水口在下边 (I型水管对应的摆放方式有6)
                DFS(x,y+1,4);               // 方式6:向上搜,向上后进水口仍为上 
                break;
        }
    }

    mark[x][y] = 0;                         // 该点尝试过后,取消标记 
    return;
}

int main()
{
    int i,j;
    cin>>n>>m;                              // 输入表示 有n*m个单位正方形 
    if(n<=0 || n>50) return -1;
    if(m<=0 || m>50) return -1;

    for(i=1;i<=n;i++)                       // 读入地图 
        for(j=1;j<=m;j++)
            cin>>map[i][j];

    top = 0;                                // 栈顶初始化为0 

    DFS(1,1,1);                             // 从(1,1)开始搜,定义一开始的进水口在左边 
    if(!flag)                               // 当前水管的设置不可能装成一个连通系统时输出 impossible 
        cout<<"impossible"<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值