题意:
在坐标系上给出n个草堆和一个拖拉机,农夫约翰要把拖拉机开到(0,0),他不能走到有草堆的点,但他可以把草堆移开后再走,求他到终点最少需要移开多少个草堆。
题解:
spfa+dp
dp[x][y]表示到(x,y)最少需要多少个草堆,直接spfa即可;
总结:
1、spfa日常做dp;
2、点格图n×m个点,满边数为2×n×m-n-m,也是n×m级别的;
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define N 1010
using namespace std;
int n,sx,sy;
int dis[N][N],g[N][N],dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
bool in[N][N];
struct Node {int x,y;};
queue<Node> q;
int gi() {
int x=0,o=1; char ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') o=-1,ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return o*x;
}
bool check(int x, int y) {
return (x>=0 && x<=1001 && y>=0 && y<=1001);
}
void spfa() {
memset(dis,63,sizeof(dis));
dis[sx][sy]=0,in[sx][sy]=1,q.push((Node){sx,sy});
while(!q.empty()) {
Node u=q.front();
int x=u.x,y=u.y;
in[x][y]=0,q.pop();
for(int i=0; i<4; i++) {
int xx=x+dx[i],yy=y+dy[i];
if(!check(xx,yy)) continue;
if(dis[xx][yy]>dis[x][y]+g[xx][yy]) {
dis[xx][yy]=dis[x][y]+g[xx][yy];
if(!in[xx][yy]) in[xx][yy]=1,q.push((Node){xx,yy});
}
}
}
}
int main() {
n=gi(),sx=gi(),sy=gi();
for(int i=1; i<=n; i++) {
int x=gi(),y=gi();
g[x][y]=1;
}
spfa();
printf("%d", dis[0][0]);
return 0;
}