第一做到双端队列广搜的题目,写个博客记录一下,并且增强一下双端队列的广搜的了解
干了一整天的活,农夫约翰完全忘记了他把拖拉机落在田地中央了。
他的奶牛非常调皮,决定对约翰来场恶作剧。
她们在田地的不同地方放了 NN 捆干草,这样一来,约翰想要开走拖拉机就必须先移除一些干草捆。
拖拉机的位置以及 NN 捆干草的位置都是二维平面上的整数坐标点。
拖拉机的初始位置上没有干草捆。
当约翰驾驶拖拉机时,他只能沿平行于坐标轴的方向(北,南,东和西)移动拖拉机,并且拖拉机必须每次移动整数距离。
例如,驾驶拖拉机先向北移动 22 单位长度,然后向东移动 33 单位长度。
拖拉机无法移动到干草捆占据的位置。
请帮助约翰确定他需要移除的干草捆的最小数量,以便他能够将拖拉机开到二维平面的原点。
输入格式
第一行包含三个整数:NN 以及拖拉机的初始位置 (x,y)(x,y)。
接下来 NN 行,每行包含一个干草捆的位置坐标 (x,y)(x,y)。
输出格式
输出约翰需要移除的干草捆的最小数量。
数据范围
1≤N≤50000
1≤x,y≤1000
输入样例:
7 6 3
6 2
5 2
4 3
2 1
7 3
5 4
6 4
输出样例:
1
题目是在一个1000*1000的矩阵里,他会告诉我们哪些地方有障碍,我们需要从给顶的起点x,y到达原点(0,0),这道题目本来是寒假的每日一题,结果那时候我连前缀和都不熟悉,所以对于双端队列广搜bfs更没有什么涉及,然后我现在回去重新做,发现了这就是一个简化版的Dijkstra,从给定起点开始,因为要求最短路,我们每次将遍历到的结点加入队列,如果该节点是存在障碍,就将dist值加一,并将该节点加入队尾,若该节点不存在障碍,则将该节点加入队首,这样第一个到达原点的值就是最小要消灭的障碍数:
注:一定要主义搜的时候不能直接将障碍值小的节点加入队列,要判断遍历到的节点的x是否在0到1001之内,y是否在0到1001之内,并且每次出队都要判重,否则会超时。
代码如下:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<deque>
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1010;
#define x first
#define y second
bool cmp(ll a, ll b)
{
return a < b;
}
bool cmp2(ll a, ll b)
{
return a > b;
}
ll g[N][N];
ll dist[N][N],st[N][N];
ll bfs(ll sx,ll sy)
{
deque<PII>q;
q.push_front({ sx,sy });
memset(dist, 0x3f, sizeof(dist));
dist[sx][sy] = 0;
int dx[4] = { 0,1,0,-1 }, dy[4] = { 1,0,-1,0 };
while (q.size())
{
auto t = q.front(); q.pop_front();
if (st[t.x][t.y])continue;
st[t.x][t.y] = 1;
if (t.x == 0 && t.y == 0)break;
ll x, y;
for (int i = 0; i <= 3; i++)
{
x = dx[i] + t.x, y = dy[i] + t.y;
if (x <= 1001 && x >= 0 && y <= 1001 && y >= 0)
{
int w = 0;
if (g[x][y] == 1)w = 1;
if (dist[x][y] > dist[t.x][t.y] + w)
{
dist[x][y] = dist[t.x][t.y] + w;
if (w == 1)q.push_back({ x,y });
else q.push_front({ x,y });
}
}
}
}
return dist[0][0];
}
void work()
{
ll n, sx,sy;
cin >> n >> sx >> sy;
for (int i = 1; i <= n; i++)
{
ll x, y;
cin >> x >> y;
g[x][y] = 1;
}
cout << bfs(sx, sy) << "\n";
}
int main()
{
ll t = 1;
//cin >> t;
while (t--)
{
work();
}
return 0;
}