题解 P2873 【[USACO07DEC]Mud Puddles S】
Horizon20182201 · · 题解
这题吸引我的地方竟然是它的题目。。。
Mud Puddles
一下我就想到了
大家都喜欢跳泥坑!!!
好了我们言归正传
这题其实是个裸的bfs
一道很好的练手题
先来看看题目中的重点:
“FJ的屋子在平面坐标(0, 0)的位置,贝茜所在的牛棚则位于坐标(X,Y) (-500 <= X <= 500; -500 <= Y <= 500)处。”
what?负数?USACO您在逗我?
其实面对负数,我们只要把坐标加上500即可,同时也不要忘记存储地图的数组也要相应增加大小。
“最少要走多少路才能到贝茜所在的牛棚呢?”
这。。。说的要多明显有多明显,就差一句“这题请用宽搜解决”。
“你可以认为从FJ的屋子到牛棚总是存在至少一条不经过任何泥塘的路径。”
这就是说此题一定有解,无需考虑走不通的情况。
好的我们先把代码贴上来
#include<bits/stdc++.h>
using namespace std;
int X,Y,n,dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//dir数组存储四个方向
bool mmap[1005][1005];//存储地图(注意这里不是500而是1000)
struct node{
int x,y,sum;
};//定义结构体,x表示横坐标,y表示纵坐标,sum表示到这个点所需步数
queue <node> qwq;//当然要符合我们小猪佩奇的可爱气质啦
int bfs ()//宽搜
{
while (!qwq.empty())//队列非空
{
int xx,yy,s;
xx=qwq.front().x;
yy=qwq.front().y;
s=qwq.front().sum;//取队首元素进行扩展
for (int i=0;i<4;i++)//4个方向
{
int nx=xx+dir[i][0],
ny=yy+dir[i][1];//扩展
if (nx==X && ny==Y)//如果到达目的地
{
while (!qwq.empty())
qwq.pop();//清空队列
return s+1;//返回值
}
else//没有到达目的地
{
if (!mmap[nx][ny])//可以走(即这里不是泥坑)
{
mmap[nx][ny]=true;//把这里标记成走过的
//其实可以再开一个vis数组,但对于这题完全没必要
qwq.push({nx,ny,s+1});//入队
}
}
}
qwq.pop();//出队
}
}
int main()
{
scanf ("%d%d%d",&X,&Y,&n);//输入
memset (mmap,false,sizeof (mmap));//初始化
X+=500; Y+=500;//重要!!!一定要加500!!!
qwq.push({500,500,0});//初始情况入队
for (int i=1;i<=n;i++)
{
int a,b;
scanf ("%d%d",&a,&b);
a+=500; b+=500;//坐标加500
mmap[a][b]=true;//标记泥坑
}
printf ("%d\n",bfs ());//输出
return 0;//完结撒花
}
另附宽搜模板
初始状态入队;
while(队列不为空)
{
取队首元素进行扩展;
for(对所有可能的拓展状态)
{
if(新状态合法)
入队;
if(当前状态是目标状态)
处理(输出解或比较解的优劣);
}
队首结点扩展完毕,出队;
}