P1849:P1849 [USACO12MAR] Tractor S - 洛谷 | 计算机科学教育新生态 https://www.luogu.com.cn/problem/P1849
最少要移动多少堆干草 John 才能将拖拉机开回坐标原点。
像一般的bfs一样搜索,只不过遇到有干草堆的就往队列后面加,否则就正常地加到队列的前面。
原理:保证了在队列前面的点需要经过的干草堆始终小于或等于在队列后面的点,因此搜索到原点的时候也可以保证此时经过的干草堆是最少的。
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0' || ch>'9')
{
if(ch=='-')w=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
int n;
int xx,yy;
int nn,mm;
int mv[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int mapp[1111][1111];
int mark[1111][1111];
int cnt;
struct node{
int x,y,step;
};
void bfs()
{
deque<node>que; //双端队列,STL大法好!!
node head;
head.x=0; //从原点开始搜
head.y=0;
mark[0][0]=1; //总觉得从原点开始搜会快一点
head.step=0;
que.push_back(head); //与一般的队列没什么区别,主要就是push与pop的时候需要加上front(从队头)或者back(从队尾)
while(!que.empty())
{
int x=que.front().x;
int y=que.front().y;
int s=que.front().step;
que.pop_front();
if(x==xx && y==yy) //搜索到目标点,此时的答案必定是最优答案(上面已经解释过了)
{
cout<<s;
return ;
}
for(int i=0;i<4;i++)
{
int tx=x+mv[i][0];
int ty=y+mv[i][1];
if(tx>=0 && tx<=nn && ty>=0 && ty<=mm && !mark[tx][ty])
{
mark[tx][ty]=1;
node t;
t.x=tx;
t.y=ty;
t.step=s;
if(!mapp[tx][ty])
{
que.push_front(t); //没遇到干草堆,队头加入
}
else
{
t.step=s+1;
que.push_back(t); //遇到了干草堆,从队尾加入
}
}
}
}
}
int main()
{
n=read();
xx=read();
yy=read();
for(int i=1;i<=n;i++)
{
int a,b;
a=read();
b=read();
mapp[a][b]=1;
nn=max(nn,a);
mm=max(mm,b);
}
nn++;mm++;//同上
bfs();//只需要搜索一次
return 0;
}