目录
题目描述
农夫约翰疯了,在一块田地里筑起了一个巨大的栅栏迷宫。幸运的是,他在迷宫的边缘拿走了两段栅栏,从而为迷宫创造了两个“出口”。更令人高兴的是,他用这种栅栏创造出的迷宫是一个“完美”的迷宫:你可以从迷宫内部的任何一点找到走出迷宫的方法。
设W (1 <= W <= 38),迷宫宽度;H (1 <= H <= 100),迷宫高度;2*H+1行,每行2*W+1个字符以下面的方式表示迷宫的结构——然后计算出从迷宫中“最糟糕”的一点走出迷宫所需的步数(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)。当然,牛只与x-y轴平行或垂直行走;它们不走对角线。每一次移动到一个新的方块都算作一个距离单位(包括“走出”迷宫)。
这是一个特定的W=5, H=3迷宫的样子:
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
(为了保持迷宫格式,我只好这样)
栅栏的柱子只出现在奇数行或奇数列(如示例中所示)。这应该是显而易见而且不言自明的。每一个迷宫都只有两个出口。
程序名:maze1
输入格式
第一行: | W和H,迷宫大小 |
---|---|
第二到第2*H+2行: | 2*W+1个字符表示迷宫 |
输入样例(文件 maze1.in)
5 3
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
输出格式
单个输出行上的单个整数。整数为保证奶牛可以从迷宫中任意一点走出迷宫的最小步骤数。
输出样例(文件 maze1.out)
9
左下角距离最近的出口9步。
解题思路
乍一看不难,我随便想想就用了深搜,从每一点向出口搜寻,结果首先在输入卡住了。读字符串的时候读到空格就停了,读字符也读不进空格。到网上一查,用了getline函数,直接读取一行,总算行了。然后深搜做完,一测,发现不对,过了好长时间才发现错误。更改了以后重新测,结果又超时了,再怎么优化也不行。请大神帮我优化一下(不过大神好像不看这种博客)。于是在网上看别人的博客,改用了广搜。先找到出口,从出口往内部搜,把遇到的每一个格子加入队列,再搜队列的第一个,然后消除第一个,直到队列为空时退出。记住要把每一个搜索过的格子记下来,避免重复。
代码
废的深搜:
/*
PROB:maze1
LANG:C++
*/
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
int w,h; //迷宫的宽与高
int mini[100][38]; //每一块走出迷宫的最短路径
bool fence[100][38][4]; //每一块的四面是否有栅栏
bool findd[100][38]; //每一块是否被搜索过
int i,j;
ifstream in("maze1.in");
ofstream out("maze1.out");
int work(int i,int j)
{
int new1=100000;
int new2;
findd[i][j]=1; //本次已搜索过
if(!fence[i][j][0])
if(i-1<0)
{
new1=0;
goto _1;
}
else if(!findd[i-1][j])
{
if(mini[i-1][j]!=0)
new2=mini[i-1][j];
else
new2=work(i-1,j);
if(new2<new1)
new1=new2;
}
if(!fence[i][j][1])
if(j+1>=w)
{
new1=0;
goto _1;
}
else if(!findd[i][j+1])
{
if(mini[i][j+1]!=0)
new2=mini[i][j+1];
else
new2=work(i,j+1);
if(new2<new1)
new1=new2;
}
if(!fence[i][j][2])
if(i+1>=h)
{
new1=0;
goto _1;
}
else if(!findd[i+1][j])
{
if(mini[i+1][j]!=0)
new2=mini[i+1][j];
else
new2=work(i+1,j);
if(new2<new1)
new1=new2;
}
if(!fence[i][j][3])
if(j-1<0)
new1=0;
else if(!findd[i][j-1])
{
if(mini[i][j-1]!=0)
new2=mini[i][j-1];
else
new2=work(i,j-1);
if(new2<new1)
new1=new2;
} //搜索
_1:new1++; //从此格走到另一格,需要一步
findd[i][j]=0;
return new1;
}
int main()
{
in>>w>>h;
string a;
getline(in,a); //跳过第一行
for(i=0;i<h*2+1;i++)
{
getline(in,a); //读入整行
for(j=0;j<w*2+1;j++)
{
if(a[j]=='|')
{
if(j!=0)
fence[i/2][j/2-1][1]=1;
if(j/2<w)
fence[i/2][j/2][3]=1;
}
else if(a[j]=='-')
{
if(i!=0)
fence[i/2-1][j/2][2]=1;
if(i/2<h)
fence[i/2][j/2][0]=1;
}
}
} //读入
int ma=0;
for(i=0;i<h;i++)
for(j=0;j<w;j++)
{
mini[i][j]=work(i,j);
if(mini[i][j]>ma)
ma=mini[i][j];
}
out<<ma<<endl;
in.close();
out.close();
return 0;
}
广搜:
/*
PROB:maze1
LANG:C++
*/
#include <fstream>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
int w,h; //迷宫的宽与高
int mini[100][38]; //每一块走出迷宫的最短路径
bool fence[100][38][4]; //每一块的四面是否有栅栏
bool findd[100][38]; //每一块是否被搜索过
struct point{int x,y;};
queue <point>q; //广搜队列
int i,j;
ifstream in("maze1.in");
ofstream out("maze1.out");
void work(int t,int i,int j)
{
if(q.empty())
return;
q.pop();
point p;
if(!fence[i][j][0]&&i!=0)
if(!findd[i-1][j])
{
p.x=i-1;
p.y=j;
if(t+1<mini[i-1][j])
mini[i-1][j]=t+1;
findd[i-1][j]=1;
q.push(p);
}
if(!fence[i][j][1]&&j!=w-1)
if(!findd[i][j+1])
{
p.x=i;
p.y=j+1;
if(t+1<mini[i][j+1])
mini[i][j+1]=t+1;
findd[i][j+1]=1;
q.push(p);
}
if(!fence[i][j][2]&&i!=h-1)
if(!findd[i+1][j])
{
p.x=i+1;
p.y=j;
if(t+1<mini[i+1][j])
mini[i+1][j]=t+1;
findd[i+1][j]=1;
q.push(p);
}
if(!fence[i][j][3]&&j!=0)
if(!findd[i][j-1])
{
p.x=i;
p.y=j-1;
if(t+1<mini[i][j-1])
mini[i][j-1]=t+1;
findd[i][j-1]=1;
q.push(p);
} //加入队列
p=q.front();
work(mini[p.x][p.y],p.x,p.y);
}
void pass(int i,int j)
{
point p;
p.x=i;
p.y=j;
q.push(p);
findd[i][j]=1;
mini[i][j]=1;
work(1,i,j);
}
int main()
{
in>>w>>h;
string a;
getline(in,a); //跳过第一行
for(i=0;i<h*2+1;i++)
{
getline(in,a); //读入整行
for(j=0;j<w*2+1;j++)
{
if(a[j]=='|')
{
if(j!=0)
fence[i/2][j/2-1][1]=1;
if(j/2<w)
fence[i/2][j/2][3]=1;
}
else if(a[j]=='-')
{
if(i!=0)
fence[i/2-1][j/2][2]=1;
if(i/2<h)
fence[i/2][j/2][0]=1;
}
}
} //读入
memset(mini,10000,sizeof(mini));
for(i=0;i<h;i++)
{
if(!fence[i][w-1][1])
{
memset(findd,0,sizeof(findd));
pass(i,w-1);
}
else if(!fence[i][0][3])
{
memset(findd,0,sizeof(findd));
pass(i,0);
}
}
for(j=0;j<w;j++)
{
if(!fence[h-1][j][2])
{
memset(findd,0,sizeof(findd));
pass(h-1,j);
}
if(!fence[0][j][0])
{
memset(findd,0,sizeof(findd));
pass(0,j);
}
} //寻找出口并广搜
_2:int ma=0;
for(i=0;i<h;i++)
for(j=0;j<w;j++)
if(mini[i][j]>ma)
ma=mini[i][j];
out<<ma<<endl;
in.close();
out.close();
return 0;
}