啊哈算法---水管工游戏
游戏大致规则是:一块矩形土地被分成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\n"); else printf("铺设成功\n"); 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("\n"); 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\n"); else printf("管道铺设成功\n"); getchar(); getchar(); return 0; }