【NOIP模拟题】【最短路】【DP】2016.11.11第一题tractor题解

1. tractor
题目描述
农场上有N(1 <= N <= 50,000)堆草,放在不同的地点上。FJ有一辆拖拉机,也在农场上。拖拉机和草堆都表示为二维平面上的整数坐标,坐标值在1..1000的范围内。拖拉机的初始位置与所有草堆不同。
FJ开拖拉机时,只能平行于坐标轴(即东、南、西、北四个方向),而且每次开动的一段必须是整数长度。
例如,他可以向北开2个单位长度,然后向东开3个单位长度。拖拉机不能开到草堆的位置。
请帮助FJ计算出最少要移动多少个草堆,他才能将拖拉机开回坐标原点。
拖拉机可以开到1..1000之外的地方去。
输入
第1行: 3个整数,即N 和拖拉机的初始位置 (x,y)
第2..1+N行: 每行2个整数,表示一堆草的位置 (x,y)
输出
第1行: FJ必须移动的最少的草堆的数量
样例输入
7 6 3
6 2
5 2
4 3
2 1
7 3
5 4
6 4
样例输出

1

本题提供两种做法

1.最短路

当走到边界时就可以乱跑了啦啦啦。

所以我们就往边界跑。

2.我的某Lee姓Friend给出了一个比较迷的解法,根据方向与顺序跑8次DP。

最短路代码:

#include <cstdio>
#include <queue>

using namespace std;

struct Point
{
	int x,y;
	Point(int _x, int _y)
	{
		x = _x;
		y = _y;
	}
	Point(void)
	{
		x=y=0;
	}
};
queue<Point>zero_away,one_away;
int A[1002][1002],D[1002][1002];

int relax(int curx, int cury, int x, int y)
{
	if (x>=0 && x<=1001 && y>=0 && y<=1001 && (D[x][y]==0 || D[curx][cury]+A[x][y]<D[x][y]))
	{
		D[x][y] = D[curx][cury]+A[x][y];
		if (A[x][y]==0)
			zero_away.push(Point(x,y));
		else one_away.push(Point(x,y));
	}
}

int main()
{
	Point p;
	int i, n;
	freopen("tractor.in", "r", stdin);
	freopen("tractor.out", "w", stdout);
	scanf("%d%d%d",&n,&p.x,&p.y);
	D[p.x][p.y] = 1;
	zero_away.push(p);
	for(i = 0; i < n; i++)
	{
		scanf ("%d%d",&p.x,&p.y);
		A[p.x][p.y] = 1;
	}
	while(!zero_away.empty() || !one_away.empty()) {
		if(zero_away.empty()) 
			while(!one_away.empty())
			{
				zero_away.push(one_away.front());
				one_away.pop();
			}
		p = zero_away.front();
		zero_away.pop();
		relax(p.x,p.y,p.x-1,p.y);
		relax(p.x,p.y,p.x+1,p.y);
		relax(p.x,p.y,p.x,p.y-1);
		relax(p.x,p.y,p.x,p.y+1);
	}
	printf ("%d\n", D[0][0]-1);
	return 0;
}

DP代码(以下为lemonoil的代码):

原文章http://blog.csdn.net/lemonoil/article/details/53130792?locationNum=2&fps=1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define N 100005
#define NAME "tractor"
#define minn(x,y,z) x=min(x,min(y,z))
using namespace std;
inline void readin(int &res) {
	static char ch;
	while ((ch = getchar()) < '0' || ch > '9');
		res = ch - 48;
	while ((ch = getchar()) >= '0' && ch <= '9')
		res = res * 10 + ch - 48;
}
struct node{
	int x,y;
};
int a[1005][1005];
int dp[1005][1005];
queue<node> q;
int n,r,c,op;
int ans=INF;

void dfs(){
	while(!q.empty()){
		node k=q.front();q.pop();
		node t;
		if(k.x==0&&k.y==0){
			ans=0;return;
		}
		if(k.x>1000||k.y>1000||k.x<0||k.y<0){
			ans=0;return;
		}
		if(!a[k.x+1][k.y]&&!dp[k.x+1][k.y]){
			dp[k.x+1][k.y]=1;t.x=k.x+1;t.y=k.y;
			q.push(t);
		}
		if(!a[k.x][k.y+1]&&!dp[k.x][k.y+1]){
			dp[k.x][k.y+1]=1;t.x=k.x;t.y=k.y+1;
			q.push(t);
		}
		if(!a[k.x][k.y-1]&&!dp[k.x][k.y-1]){
			dp[k.x][k.y-1]=1;t.x=k.x;t.y=k.y-1;
			q.push(t);
		}
		if(!a[k.x-1][k.y]&&!dp[k.x-1][k.y]){
			dp[k.x-1][k.y]=1;t.x=k.x-1;t.y=k.y;
			q.push(t);
		}
	}
}

int main(){
	freopen(NAME".in","r",stdin);
	//freopen(NAME".out","w",stdout);
	readin(n);readin(r);readin(c);
	for(int x,y,i=1;i<=n;i++){
		readin(x);readin(y);a[x][y]=1;
	}
	node k;
	k.x=r,k.y=c;
	clr(dp);
	//dfs();
	clr(dp);
	for(int i=0;i<=1001;i++){
		for(int j=0;j<=1001;j++){
			dp[i][j]=min(dp[i-1][j],dp[i][j-1]);
			dp[i][j]+=a[i][j];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=1001;i>=0;i--){
		for(int j=0;j<=1001;j++){
			dp[i][j]=min(dp[i+1][j],dp[i][j-1]);
			dp[i][j]+=a[i][j];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=0;i<=1001;i++){
		for(int j=1001;j>=0;j--){
			dp[i][j]=min(dp[i-1][j],dp[i][j+1]);
			dp[i][j]+=a[i][j];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=1001;i>=0;i--){
		for(int j=1001;j>=0;j--){
			dp[i][j]=min(dp[i+1][j],dp[i][j+1]);
			dp[i][j]+=a[i][j];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=0;i<=1001;i++){
		for(int j=1001;j>=0;j--){
			dp[j][i]=min(dp[j+1][i],dp[j][i-1]);
			dp[j][i]+=a[j][i];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=0;i<=1001;i++){
		for(int j=0;j<=1001;j++){
			dp[j][i]=min(dp[j-1][i],dp[j][i-1]);
			dp[j][i]+=a[j][i];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=1001;i>=0;i--){
		for(int j=1001;j>=0;j--){
			dp[j][i]=min(dp[j+1][i],dp[j][i+1]);
			dp[j][i]+=a[j][i];
		}
	}
	ans=min(ans,dp[r][c]);
	clr(dp);
	for(int i=1001;i>=0;i--){
		for(int j=0;j<=1001;j++){
			dp[j][i]=min(dp[j-1][i],dp[j][i+1]);
			dp[j][i]+=a[j][i];
		}
	}
	cout<<dp[r][c];
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值