2018.5.5 T2点

文件名newbarn.c/cpp/pas 时间限制1s 内存限制128M

题目描述

N个二维坐标上的整数点(Xi,Yi)。现在请你选择一个不与N个点重合的整数点(X,Y)。最小化距离(保证点不相邻)

输入格式(输入文件newbarn.in

第一行一个整数N

接下来N行,每行两个整数XiYi

输出格式(输出文件newbarn.out

两个整数。最小距离和可行位置个数。

样例数据

Input

4

1 -3

0 1

-2 1

1 -1

output

10 4

解释:(0,−1), (0, 0), (1, 0), (1, 1)

数据规模

2<=N<=10000

其他数字绝对值小于等于10000

-----------------------------------------------------------

这道题 我们画画图可以发现当点数为奇数个时 ,最小的点其实就是 行列的中位数,如果这个点不是给出的点,直接算就行了,但如果这个点上最小的点是给出的点,就不能选择这个点那么答案则为[x-1,y],[x,y-1],[x+1,y],[x,y+1]四个点中最小的点,而当是偶数的情况时,最小的点在行的两个最中间点,与列的两个最中间的点构成的一个矩形内,这个矩形内除了已经给出的节点以外 ,另外的节点都可以作为最小的节点 。正确性显然

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+7;
struct point {
	int x,y;
}p[N];
int x[N],y[N];
int mx[4]={1,0,-1,0},my[4]={0,1,0,-1};
int n,ans=1e9,num;
int abs(int x) {return x<0?-x:x;}
bool check(int x,int y) {
	for (int i=1;i<=n;i++)
		if (p[i].x==x && p[i].y==y) return 0;
	return 1;
}
int pre(int x,int y) {
	int res=0;
	for (int i=1;i<=n;i++)
		res+=abs(p[i].x-x)+abs(p[i].y-y);
	return res;
}
int main() {
	freopen("newbarn.in","r",stdin);
	freopen("newbarn.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) {
		scanf("%d%d",&x[i],&y[i]);
		p[i].x=x[i];p[i].y=y[i];
	}
	sort(x+1,x+n+1);
	sort(y+1,y+n+1);
	if (n&1) {
		int X=x[n/2+1],Y=y[n/2+1];
		if (check(X,Y)) {
			ans=pre(X,Y);num=1;
		}
		else {
			for (int i=0;i<4;i++) {
				int xx=X+mx[i],yy=Y+my[i];
				int val=pre(xx,yy);
				if (val<ans) ans=val,num=1;
				else if (val==ans) num++;
			}
		}
	}
	else {
		int Xi=x[n/2],Xx=x[n/2+1],Yi=y[n/2],Yx=y[n/2+1];
		ans=pre(Xx,Yx);
		num=abs(Xx-Xi+1)*abs(Yx-Yi+1);
		for (int i=1;i<=n;i++)
			if (p[i].x>=Xi && p[i].x<=Xx && p[i].y>=Yi && p[i].y<=Yx) num--;
	}
	printf("%d %d\n",ans,num);
}

还有亲民的90,找到中心点,暴力枚举一个矩阵(其实只要枚举边长几十,暴力计算)

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+7;
int x[N],y[N],sx[N],sy[N],vis[N<<1];
int n,ans=1e9+7,num,X,Y;
#define dd c=getchar()
int read(){int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<'9') s=s*10+c-'0',dd;return w*s;}
#undef dd
vector<int> v[20005];
int main() {
	freopen("newbarn.in","r",stdin);
	freopen("newbarn.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) {
		scanf("%d%d",&x[i],&y[i]);
		v[x[i]+10000].push_back(y[i]+10000);
	}
	sort(x+1,x+n+1);
	sort(y+1,y+n+1);
	if (n&1) {
		X=x[n/2+1];Y=y[n/2+1];
	}
	else X=(x[n/2]+x[n/2+1])/2,Y=(y[n/2]+y[n/2+1])/2;
	y[0]=x[0]=-1e9;y[n+1]=x[n+1]=1e9;
	for (int i=1;i<=n;i++) {
		sx[i]=sx[i-1]+x[i];sy[i]=sy[i-1]+y[i];
	}
	int kx=lower_bound(x+1,x+n+1,X-3000)-x-1;
	int ky=lower_bound(y+1,y+n+1,Y-3000)-y-1;
	for (int i=max(-10000,X-3000);i<=min(10000,X+3000);i++) {
		while (i>x[kx+1] && kx<n) kx++;
		memset(vis,0,sizeof vis);
		for (int j=0;j<v[i+10000].size();j++) {
			vis[v[i+10000][j]]=1;
		}
		int k=ky;
		for (int j=max(-10000,Y-3000);j<=min(10000,Y+3000);j++) {
			while (j>y[k+1] && k<n) k++;
			if (vis[j+10000]) continue;
			int res=i*kx-sx[kx]+sx[n]-sx[kx]-i*(n-kx)+j*k-sy[k]+sy[n]-sy[k]-j*(n-k);
			if (res<ans) ans=res,num=1;
			else if (res==ans) num++;
		}
	}
	printf("%d %d\n",ans,num);
}



猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80208284
T2