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


    游戏大致规则是:一块矩形土地被分成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;
    }

  • 相关阅读:
    《更好的解释(数学篇)》——第一章
    流密码及RC4算法ZZ
    Android
    Android中Handler 、Thread和Runnable之间的关系ZZ
    Android之Handler消息传递机制详解zz
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之四(三十)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之三(二十九)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之二(二十八)
    abp(net core)+easyui+efcore实现仓储管理系统——ABP WebAPI与EasyUI结合增删改查之一(二十七)
    abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理八(二十六)
  • 原文地址:https://www.cnblogs.com/lxt1105/p/6437272.html
Copyright © 2020-2023  润新知