一中180505模拟赛T2 点

针对一组二维坐标上的整数点,本算法探讨如何选择一个既不在这些点上又能使距离最小化的整数点,并计算最小距离及可行位置的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件名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。


题解:

也不能说是题解吧,我自己最后打着打着发现我的方法(可以说成是半个贪心吧)是错误的。留着代码当做纪念,再感受一下吧

 

代码(PS:还没打完,还有将近一半)

#include<bits/stdc++.h>
using namespace std;
long long n,l,r,ll,rr,num,flag,p=1000003,minl,maxl,minh,maxh,g[2000000],gg[2000000],ggg[2000000],sum,ans,ha[1000000],lie[1000000],a[1000000],b[1000000],aa[1000000],bb[1000000],qh[1000000],ql[1000000];
long long hash(long long t,long long l,long long r){
	long long i=t%p;
	while(g[i]&&(gg[i]!=l||ggg[i]!=r))i=(i+1)%p;
	return i;
}
int main(){
//freopen("newbarn.in","r",stdin);
//freopen("newbarn.out","w",stdout);
long long t,k,i,j;	
	scanf("%lld",&n);
	minh=100000000;minl=100000000;
	for(i=1;i<=n;i++){
		scanf("%lld%lld",&a[i],&b[i]);
		t=a[i]*b[i];
		k=hash(t,a[i],b[i]);
		g[k]=1;gg[i]=a[i];ggg[i]=b[i];
		a[i]+=100000;b[i]+=100000;
		ha[a[i]]++;lie[b[i]]++;
		minh=min(minh,a[i]);maxh=max(maxh,a[i]);
		minl=min(minl,b[i]);maxl=max(maxl,b[i]);
}
	for(i=minh+1;i<=maxh;i++)aa[i]=aa[i-1]+ha[i-1];
	for(i=minh;i<=maxh;i++)qh[i]=qh[i-1]+n-aa[i]-aa[i];
	for(i=minh;i<=maxh;i++)
	 if(qh[i]>sum){
	 	sum=qh[i];
	 	l=i;
	 }
	 for(i=maxh;i>=minh;i--)
	  if(qh[i]==sum){
	  	r=i;
	  	break;
	  }      
	sum=0; 
	for(i=minl+1;i<=maxl;i++)bb[i]=bb[i-1]+lie[i-1];
	for(i=minl;i<=maxl;i++)ql[i]=ql[i-1]+n-bb[i]-bb[i];
	for(i=minl;i<=maxl;i++)
	 if(ql[i]>sum){
	 	sum=ql[i];
	 	ll=i;
	 }       
	for(i=maxl;i>=minl;i--)
	 if(ql[i]==sum){
	 	rr=i;
	 	break;
	 }        
	 sum=0;
	 for(i=1;i<=n;i++)sum+=abs(l-a[i])+abs(ll-b[i]);
	 num=1000000000;
	ans=(r-l+1)*(rr-ll+1); 
	for(i=1;i<=n;i++)
	 if(a[i]>=l&&a[i]<=r&&b[i]>=ll&&b[i]<=rr){
	 	ans--;
	 }   
	if(ans==0){
	//左上角
	flag=0;
	for(ii=1;ii<=200;ii++){
		for(i=l-ii;i<l;i++){
			j=ll-ii;
			t=i*j;
		 	k=hash(t,i,j);
		 	if(!g[k]){
			 if(sum+qh[l]-qh[i]+ql[ll]-ql[j]<num){
			 	num=sum+qh[l]-qh[i]+ql[ll]-ql[j];
			 	ans=1;
			 }
			  else if(sum+qh[l]-qh[i]+ql[ll]-ql[j]==num)ans++;
			  flag=1;
		}		
	} 
	for(j=ll-ii;j<ll;j++){
		i=l-ii;
		t=i*j;
		 	k=hash(t,i,j);
		 	if(!g[k]){
			 if(sum+qh[l]-qh[i]+ql[ll]-ql[j]<num){
			 	num=sum+qh[l]-qh[i]+ql[ll]-ql[j];
			 	ans=1;
			 }
			  else if(sum+qh[l]-qh[i]+ql[ll]-ql[j]==num)ans++;
			  flag=1;
		}	
	}
	
}
		 flag=0;
		 for(i=l-1;i>=minh-1;i--){
		 	for(j=ll;j<=rr;j++){
		 		t=i*j;
		 	k=hash(t,i,j);
		 	if(!g[k]){
			 if(sum+qh[l]-qh[i]<num){
			 	num=sum+qh[l]-qh[i];
			 	ans=1;
			 }
			  else if(sum+qh[l]-qh[i]==num)ans++;
			  flag=1;break;
		}
		 }if(flag)break;}
		 flag=0;
		 for(i=r+1;i<=maxh+1;i++){
		 	for(j=ll;j<=rr;j++){
		 		t=i*j;
		 	k=hash(t,i,j);
		 	if(!g[k]){
			 if(sum+qh[i]-qh[r]<num){
			 	num=sum+qh[i]-qh[r];
			 	ans=1;
			 }
			  else if(sum+qh[i]-qh[r]==num)ans++;
			  flag=1;break;
			 }
		 }
		 if(flag)break;
	}
	flag=0;
		 for(i=ll-1;i>=minl-1;i--){
		 	for(j=l;j<=r;j++){
		 		t=i*j;
		 		k=hash(t,i,j);
		 		if(!g[k]){
				 if(sum+ql[ll]-ql[i]<num){
				 	num=sum+ql[ll]-ql[i];
				 	ans=1;
				 }
				  else if(sum+ql[ll]-ql[i]==num)ans++;
			flag=1;break;
		}
			 }
			 if(flag)break;
		 }
		 flag=0;
		 for(i=rr+1;i<=maxl+1;i++){
		 	for(j=l;j<=r;j++){
		 		t=i*j;
		 		k=hash(t,i,j);
		 		if(!g[k]){
				 if(sum+ql[i]-ql[rr]<num){
				 	num=sum+ql[i]-ql[rr];
				 	ans=1;
				 }
				  else if(sum+ql[i]-ql[rr]==num)ans++;
			flag=1;break;
		}
			 }
			 if(flag)break;
		 }
		printf("%lld %lld",num,ans);
		return 0; 
	}              
	printf("%lld %lld",sum,ans); 	 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值