啊哈算法---水管工游戏

游戏大致规则是:一块矩形土地被分成N*M的单位正方形,现在这块土地已经埋设了一些水管。

水管将从矩形土地的左上角左部边缘,延伸到右下角右部边缘。

水管只有两种:弯管和直管

弯管有四种状态

直管有两种状态

0,1,2,3,4,5,6分别表示:0表示树木,1,2,3,4表示弯管四种状态。5,6表示直管两种状态。

程序需要判断进水口:进水口在左边用1表示;在上边用2表示;在右边用3表示;在下边用4表示。

/*水管工:铺设管道*/

#include<stdio.h>

int a[51][51];//假设土地大小不超过50*50
int book[51][51];
int n, m, flag = 0;
void dfs(int x, int y, int front)//front:定义四个方向左上右下分别为1234
{
//    int i;
    //判断是否到达终点,(n,m+1)
    //另外判断是否到达终点必须放在越界前面判断
    if (x == n && y == m + 1)
    {
        flag = 1; //找到铺设方案
        return;
    }

    //判断是否越界
    if (x<1 || x>n || y<1 || y>m)
        return;
    //判断这个管道是否在路径中已经使用过
    if (book[x][y] == 1)
        return;
    book[x][y] = 1;//标记使用当前这个管道

    //当前管道是直管情况
    if (a[x][y] >= 5 && a[x][y] <= 6)
    {
        //直管有四个方向,需要逐个判断
        if (front == 1) //水从左边进
        {
            dfs(x, y + 1, 1);//只能使用5号这种摆放方式
        }
        
        if (front == 2)//水从上边进
        {
            dfs(x + 1, y, 2);//6号
        }
    
        if (front == 3)//水从右边进
        {
            dfs(x - 1, y, 3);//5号
        }

        if (front == 4)//水从下边进
        {
            dfs(x, y - 1, 4);//6号
        }

    }

    //当前水管是弯管的情况
    if (a[x][y] >= 1 && a[x][y] <= 4)
    {
        if (front == 1)//水从左边进
        {
            dfs(x + 1, y, 2); //3号
            dfs(x - 1, y, 4);//4号
        }
        if (front == 2)//水从上边进
        {
            dfs(x, y + 1, 1);//1号
            dfs(x, y - 1, 3);//4号
        }
        if (front == 3)//水从右边进
        {
            dfs(x - 1, y, 4);//1号
            dfs(x + 1, y, 2);//2号
        }
        if (front == 4)//水从下边进
        {
            dfs(x, y + 1, 1);//2号
            dfs(x, y - 1, 3);//3号
        }

    }
    book[x][y] = 0;
    return;
}

int main()
{
    int i, j, num = 0;
    scanf_s("%d %d", &n, &m);

    //读入游戏地图
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++)
            scanf_s("%d", &a[i][j]);

    //开始搜索,从(1,1)点开始,进水方向是1
    dfs(1, 1, 1);
    //判断是否找到铺设方案
    if (flag == 0)
        printf("impossible
");
    else
        printf("铺设成功
");

    getchar(); getchar();
    return 0;
}

上面代码并没有解决最初的要求“输出路径”。只需在代码中加入一个栈,就可以输出路径。代码如下:

/*水管工:铺设管道,求输出路径*/

#include<stdio.h>

int a[51][51];//假设土地大小不超过50*50
int book[51][51];
int n, m, flag = 0;

//加入一个栈
struct note
{
    int x;//横坐标
    int y;//纵坐标
}s[100];
int top = 0;
void dfs(int x, int y, int front)//front:定义四个方向左上右下分别为1234
{
    int i;
    //判断是否到达终点,(n,m+1)
    //另外判断是否到达终点必须放在越界前面判断
    if (x == n && y == m + 1)
    {
        flag = 1; //找到铺设方案
        for (i = 1; i <= top; i++)
            printf(" (%d,%d) ", s[i].x, s[i].y);
        printf("
");
        return;
    }

    //判断是否越界
    if (x<1 || x>n || y<1 || y>m)
        return;
    //判断这个管道是否在路径中已经使用过
    if (book[x][y] == 1)
        return;
    book[x][y] = 1;//标记使用当前这个管道

    //将当前尝试的坐标入栈
    top++;
    s[top].x = x;
    s[top].y = y;

    //当前管道是直管情况
    if (a[x][y] >= 5 && a[x][y] <= 6)
    {
        //直管有四个方向,需要逐个判断
        if (front == 1) //水从左边进
        {
            dfs(x, y + 1, 1);//只能使用5号这种摆放方式
        }

        if (front == 2)//水从上边进
        {
            dfs(x + 1, y, 2);//6号
        }

        if (front == 3)//水从右边进
        {
            dfs(x - 1, y, 3);//5号
        }

        if (front == 4)//水从下边进
        {
            dfs(x, y - 1, 4);//6号
        }

    }

    //当前水管是弯管的情况
    if (a[x][y] >= 1 && a[x][y] <= 4)
    {
        if (front == 1)//水从左边进
        {
            dfs(x + 1, y, 2); //3号
            dfs(x - 1, y, 4);//4号
        }
        if (front == 2)//水从上边进
        {
            dfs(x, y + 1, 1);//1号
            dfs(x, y - 1, 3);//4号
        }
        if (front == 3)//水从右边进
        {
            dfs(x - 1, y, 4);//1号
            dfs(x + 1, y, 2);//2号
        }
        if (front == 4)//水从下边进
        {
            dfs(x, y + 1, 1);//2号
            dfs(x, y - 1, 3);//3号
        }

    }
    book[x][y] = 0;//取消标记
    top--;//将当前尝试的坐标出栈
    return;
}

int main()
{
    int i, j, num = 0;
    scanf_s("%d %d", &n, &m);

    //读入游戏地图
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++)
            scanf_s("%d", &a[i][j]);

    //开始搜索,从(1,1)点开始,进水方向是1
    dfs(1, 1, 1);
    //判断是否找到铺设方案
    if (flag == 0)
        printf("impossible
");
    else
        printf("管道铺设成功
");

    getchar(); getchar();
    return 0;
}

原文地址:https://www.cnblogs.com/lxt1105/p/6437272.html