1696: [Usaco2007 Feb]Building A New Barn新牛舍

1696: [Usaco2007 Feb]Building A New Barn新牛舍

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 378   Solved: 168
[ Submit][ Status][ Discuss]

Description

经过多年的积蓄,农夫JOHN决定造一个新的牛舍。他知道所有N(2 <= N <= 10,000)头牛的吃草位置,所以他想把牛舍造在最方便的地方。 每一头牛吃草的位置是一个整数点(X_i, Y_i) (-10,000 <= X_i <= 10,000; -10,000 <= Y_i <= 10,000)。 没有两头牛的吃草位置是相邻的。 JOHN决定把牛舍造在一个没有牛吃草的整数点上。如果牛舍在(X, Y),在(X_i, Y_i)的牛到牛舍的距离是|X-X_i|+|Y-Y_i|。 JOHN把牛舍造在哪儿才能使所有牛到牛舍的距离和最低?

Input

第1行: 一个数,N。

第2~N+1行:第i+1行 包含第i头牛的位置(X_i, Y_i)。

Output

第1行: 两个数,最小距离和和所有可能达到这个距离和的牛舍位置的数目。

Sample Input

4
1 -3
0 1
-2 1
1 -1

输入解释:

一共有4头牛,位置分别为(1, -3), (0, 1), (-2, 1), 和(1, -1).

Sample Output

10 4

输出解释:
最小距离和是10,可以在牛舍位于 (0, -1), (0, 0), (1, 0), (1, 1)时达到。


对于这种题自然要先想到中位数。。不过一开始傻傻的没考虑不能建在牛身上。。。
如果是奇数,建在中间一个数的位置,偶数在中间两个的任意位置都行
不过偶数舍去区间内刚好有牛的点,如果奇数情况且最优解在牛身上
那么次优解一定在上下左右产生

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;

const int maxn = 1e4 + 10;
const int dx[4] = {0,1,0,-1};
const int dy[4] = {1,0,-1,0};

struct C{
	int x,y;
}cow[maxn];

int x[maxn],y[maxn],n,i,j,a1,a2;

int main()
{
	#ifndef ONLINE_JUDGE
	#ifndef YZY
	  freopen(".in","r",stdin);
	  freopen(".out","w",stdout);
	#else
	  freopen("yzy.txt","r",stdin);
	#endif
	#endif

	cin >> n;
	for (i = 1; i <= n; i++) 
	{
		scanf("%d%d",&cow[i].x,&cow[i].y);
		x[i] = cow[i].x; y[i] = cow[i].y;
	}
	sort (x + 1,x + n + 1);
	sort (y + 1,y + n + 1);
	
	if (n & 1)
	{
		int tmp = (n / 2) + 1;
		for (i = 1; i <= n; i++)
		{
			if (cow[i].x == x[tmp] && cow[i].y == y[tmp])
			{
				int Min = 2E9;
				for (int l = 0; l < 4; l++)
				{
					int xx = x[tmp] + dx[l];
					int yy = y[tmp] + dy[l];
					int now = 0;
					for (i = 1; i <= n; i++) 
					  now += abs(cow[i].x - xx) + abs(cow[i].y - yy);
					if (now < Min) Min = now,a2 = 1;
					else if (now == Min) ++a2;
				}
				printf("%d %d\n",Min,a2);
				return 0;
			}
			else a1 += abs(cow[i].x - x[tmp]) + abs(cow[i].y - y[tmp]);
		}
		printf("%d 1\n",a1);
	}
	else
	{
		int t1 = n / 2,t2 = t1 + 1;
		a2 = (x[t2] - x[t1] + 1) * (y[t2] - y[t1] + 1);
		for (i = 1; i <= n; i++)
		{
			a1 += abs(cow[i].x - x[t1]) + abs(cow[i].y - y[t1]);
			int X = cow[i].x,Y = cow[i].y;
			if (x[t1] <= X && X <= x[t2] && y[t1] <= Y && Y <= y[t2]) --a2;
		}
		printf("%d %d\n",a1,a2);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值