点
文件名newbarn.c/cpp/pas 时间限制1s 内存限制128M
题目描述
有N个二维坐标上的整数点(Xi,Yi)。现在请你选择一个不与N个点重合的整数点(X,Y)。最小化距离(保证点不相邻)
输入格式(输入文件newbarn.in)
第一行一个整数N。
接下来N行,每行两个整数Xi,Yi。
输出格式(输出文件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); }