Slash Maze(uva 705)

来源:互联网 发布:sql order by limit 1 编辑:程序博客网 时间:2024/05/16 11:46

本题的亮点是dfs和‘\’ ‘/’的转化方法。我采用了比较普遍和简单的方法,使用九宫格,这样由于斜着走可以变成横着走和竖着走的组合形式,所以在移步遍历时只用考虑上下左右四个方向。

编程步骤可分为三步:

(1)输入:通过键盘输入‘\’ ‘/’,将‘\’转化为100 010 001 ,‘/’ 转化为 001 010 100,构造map数组。

(2)dfs:判断移动一步之后,是否超过了边界,由此筛出非封闭点,check标志位标记是否封闭;

               另外为了提高效率,还可以设置非封闭已遍历点,即与边界相通的点,逐步扩大边界范围;

               此处还有一个教训:开始把row写成x把col写成y,导致想成坐标,结果此处h和w的位置写反。。。。

(3)寻找Cycles数和最大长度:寻找未遍历且map值为0的点,进行dfs。

做完此题后受益匪浅啊。

代码码:

#include<iostream>#include<stdio.h>#include<string.h>//memset函数的头文件using namespace std;int w,h,length,check=1;//宽,高,围住的方块数,标志位int num=0;//Maze数int visit[250][250];//75*3=225int map[250][250];//visit为访问数组,记录该方块是否被访问过;map为输入数组,记录0,1的位置int Move[4][2]={1,0,-1,0,0,1,0,-1};//移动的方向,由于采用九宫格,只需考虑上下左右四个方向void dfs(int row,int col,int &len){//dfs 开始把row写成x把col写成y,导致想成坐标int R,C;//R是行,C是列 for (int i=0;i<4;i++){R=row+Move[i][0];C=col+Move[i][1];if ((R>=0)&&(R<3*h)&&(C>=0)&&(C<3*w)){//开始把row写成x把col写成y,导致想成坐标,结果此处h和w的位置写反。。。。if (visit[R][C]==0&&map[R][C]==0){visit[R][C]=1;len++;dfs(R,C,len);}}else check=0;}}int main(){int cycles,max;while(scanf("%d%d",&w,&h)){max=0;if (w+h==0) break;//输入0 0时的结果:无输出memset(map,0,sizeof(map));memset(visit,0,sizeof(visit));//清空map和visitnum++;for(int i=0;i<h;i++)//输入mapfor(int j=0;j<w;j++){char ch;cin>>ch;if (ch=='\\'){map[3*i][3*j]=1;map[3*i+1][3*j+1]=1;map[3*i+2][3*j+2]=1;}else if (ch=='/'){map[3*i][3*j+2]=1;map[3*i+1][3*j+1]=1;map[3*i+2][3*j]=1;}}cycles=0;for(int i=0;i<3*h;i++)for(int j=0;j<3*w;j++){length=1;//已知一点判断下一点if (visit[i][j]==0&&map[i][j]==0){visit[i][j]=1;check=1;dfs(i,j,length);  if (check==1){cycles++;if (length>max) max=length;}}}cout<<"Maze #"<<num<<":"<<endl;if (cycles>0) cout<<cycles<<" Cycles; the longest has length "<<max/3<<'.'<<endl;//注意格式else cout<<"There are no cycles."<<endl;cout<<endl;}return 0;}

ps:编程过程中查阅的一些资料:

(1)数组的存储方式。

PASCAL和C语言中,数组按行优先顺序存储。

FORTRAN语言中,数组按列优先顺序存储。

(2)输入那点儿事:

cin.get()是保留回车在输入流队列中的.而cin是丢弃回车的.所以cin.get()在下一次输入之前需要把之前的回车符给弄掉。

0 0