今天来复习一下如何用DFS找到能使首尾连接的通道,并显示出来。
题目描述
一块矩形土地被分为N*M的单位正方形,现在这块土地上已经埋设有一些水管,水管将从坐标为(1,1)的矩形土地的左上角坐标边缘,延伸到坐标为(N,M)的矩形土地的右下角右部边缘。水管有两种,弯的和直的。
每种管道将占据一个单位正方形土地。你现在可以旋转这些管道,使其构成一个管道系统,即创造一条从(1,1)到(N,M)的连通管道。标有数目的方格表示这里没有管道。
输入
输入的第一行为两个整数N,M(都不超过10),接下来的N行,每行有M个整数,表示地图中的每一小格。其中0表示数目,1~6分别表示管道的六种不同摆放方式
输出
如果通过旋转管道可以使之构成一个连通的管道系统,就输出铺设的路径,否则输出impossible。
输入样例1
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) (1,2) (2,2) (3,2) (3,3) (3,4) (4,4) (5,4)
输入样例2
5 4
3 5 2 4
1 3 2 5
2 5 3 1
2 6 1 4
2 5 4 5
输出样例2
impossible
AC代码
#include<bits/stdc++.h>
using namespace std;
int book[51][51],a[51][51];
int next[5][2]={{0,0},{0,1},{1,0},{0,-1},{-1,0}};
int top;
int n,m,flag; //flag 用来标记
struct note{
int x,y;
}s[2501]; //用栈来存储路径
void dfs(int x,int y,int t)
{
int tx,ty;
if(x==n&&y==m+1){ //如果有路径,标记flag,并输出路径
flag=1;
for(int i=1;i<=top;i++)
printf("(%d,%d)",s[i].x,s[i].y);
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(t==1){ //t=1说明管口在左侧
dfs(x,y+1,1); //管口在左侧,另一边就在右侧,就通过了右边的方格,所以y+1 , 此时对右侧的方格而言,管口还是在左侧,所以是1
}
if(t==2){ //t=2说明管口在上侧
dfs(x+1,y,2); //同理,
}
if(t==3){ //t=3说明管口在右侧
dfs(x,y-1,3);
}
if(t==4){ //t=4说明管口在下侧
dfs(x-1,y,4);
}
}
if(a[x][y]>=1&&a[x][y]<=4){
if(t==1){
dfs(x-1,y,4);
dfs(x+1,y,2);
}
if(t==2){
dfs(x,y-1,3);
dfs(x,y+1,1);
}
if(t==3){
dfs(x-1,y,4);
dfs(x+1,y,2);
}
if(t==4){
dfs(x,y-1,3);
dfs(x,y+1,1);
}
}
book[x][y]=0; //回溯
top--;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
dfs(1,1,1);
if(!flag) printf("impossible"); //如果flag没有被标记,说明没有路径,输出impossible
return 0;
}
好啦,解题完毕!!!!