[洛谷1849] 拖拉机

题意:

在坐标系上给出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;
}
posted @ 2017-10-23 23:04  HLX_Y  阅读(172)  评论(0编辑  收藏  举报