水管工游戏

来源:互联网 发布:收发短信软件 编辑:程序博客网 时间:2024/04/27 16:52

一 题目

一块矩形土地被分为N*M的单位正方形,现在这块土地上已经埋设有一些水管,水管将从坐标为(1,1)左上角左部边缘,延伸到(N,M)右下角右部边缘。水管只有2种,如下图所示。
这里写图片描述

每种管道将占据一个单位正方形土地。你现在可以旋转这些管道,使得构成一个管道系统,即创造一条从(1,1)到(N,M)的连通管道。标有树木的方格表示这里没有管道。如下图:一个5*4的土地中(2,4)处有一个树木。
这里写图片描述
我们可以旋转其中的一些管道,使之构成一个连通的管道系统,如下图。
这里写图片描述
如果通过旋转管道可以使之构成一个连通的管道系统,就输出铺设的路径,否则输出impossible。

例如输入如下数据:
5 4
5 3 5 3
1 5 3 0
2 3 5 1
6 1 1 5
1 5 5 4
输出:
(1,1)(1,2)(2,2)(3,2)(3,3)(3,4)(4,4)(5,4)

输入的第一行为俩个整数N和M(都不超过10),接下来的N行,每行都有M个整数,表示地图中的每一小格,其中0表示树木,1~6分别表示管道的六种不同的摆放方式。

二 分析

对照上图,很容易得出摆放方式与1到6的数字之间对应的情况,如下表所示:

images num 这里写图片描述 1 这里写图片描述 2 这里写图片描述 3 这里写图片描述 4 这里写图片描述 5 这里写图片描述 6

假设当前位置为 ij 列,要想知道下一步往哪个方向走,除了当前的水管外,还要知道上一步的位置。

如果当前的水管是5或者6。
假如上一步为i1j列,那么下一步只能是i+1j列。
通俗的说就是,从上面下来的,只能往下面去,不能往两边走。其他情况也是一样,就像过河一样只能过到对岸。
假如上一步为i+1j列,那么下一步只能是i1j列。
假如上一步为ij+1列,那么下一步只能是ij1列。
假如上一步为ij1列,那么下一步只能是ij+1列。

如果当前的水管是1到4中的一种。
从上面下来的,和从下面上来的,可以归为同一类,都有两种情况,要么往左,要么往右。
同理,从左边和从右边过来的可以归为一类,要么往上,要么往下。

再确定返回的条件,代码就出来了,如下,如有错误,欢迎指正。

三 编码

#include <iostream>using namespace std;int v[100];   //保存经过点的坐标int k = 0;bool flag = true;    //有无路径的标志//i和j是当前的坐标,a和b是上一步的坐标,N和M是行和列的总数void fun(int array[10][10] , int i , int j , int a , int b , int N , int M){   // cout << "当前是:" << i << "  " << j << "上一步是:" << a << "  " << b << endl;    if (i == N - 1 && j == M)  //走到了右下角的右边,说明找到路径    {        flag = false;        for (int x = 0; x < k; x += 2)        {            cout << "(" << v[x] + 1 << "," << v[x + 1] + 1 << ")" << " ";        }        cout << endl;        return;    }    for (int x = 0; x < k; x += 2)  //不能回到已经走过的点,因为走过的点管道的摆放方式已确定    {        if (v[x] == i && v[x + 1] == j)            return;    }    v[k++] = i;    v[k++] = j;    if (i < 0 || j < 0 || i >= N || j >= M || array[i][j] == 0)  //如果遇到树或者出界就返回        return;     if (array[i][j] == 5 || array[i][j] == 6)    {        if (b + 1 == j)  //从左边来        {            fun(array , i , j + 1 , i , j , N , M);        }        else if (a + 1 == i)   //从上边来        {            fun(array , i + 1, j , i , j , N , M);        }        else if (b - 1 == j)   //从右边来        {            fun(array , i , j - 1 , i , j , N , M);        }        else if (a - 1 == i)   //从下边来        {            fun(array , i - 1, j , i , j , N , M);        }    }    else if(array[i][j] >= 1 && array[i][j] <= 4)    {        if (b + 1 == j || b - 1 == j)  //从左边或右边进来        {            int t = k;   //记录此时的位置,确保从当前位置分别向两个方向寻找            fun(array , i + 1 , j , i , j , N , M);            k = t;            fun(array , i - 1 , j , i , j , N , M);        }        else if (a + 1 == i || a - 1 == i)   //从上边或下边来        {            int t = k;            fun(array , i , j + 1 , i , j , N , M);            k = t;            fun(array , i , j - 1 , i , j , N , M);        }    }}int main(){    int M , N;    cin >> N >> M;    int a[10][10];    for (int i = 0; i < N; i++)    {        for (int j = 0; j < M; j++)        {            cin >> a[i][j];        }    }    fun(a , 0 , 0 , 0 , -1 , N , M);    if(flag)    //flag为true,说明没有找到路径    {        cout << "impossible";    }    return 0;    }
0 0