国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > Mag-Warehouse 切比雪夫距离转曼哈顿距离

Mag-Warehouse 切比雪夫距离转曼哈顿距离

来源:程序员人生   发布时间:2016-04-13 08:32:21 阅读次数:3144次

题意:
给定1个网格图,其上有1堆坏点(整点,同1位置多个),求1个整点,使得该整点到所有的坏点的切比雪夫距离之和最小。
求这个整点位置。

无SPJ

解析:
看完题懵了,我只会曼哈顿距离啊怎样办。
然后就无聊查了下给定的那个计算公式,哇塞这竟然叫切比雪夫距离。
噫怎样有个链接是谈切比雪夫转化曼哈顿距离的。
噫看完后我就会这道题辣!

对原坐标系中两点间的 Chebyshev 距离,是将坐标轴顺(逆)时针旋转45度并将所有点的坐标值放大sqrt(2)倍所得到的新坐标系中的Manhattan距离的2分之1。

某点绕原点逆时针旋转α°(或坐标轴顺时针旋转)后,点(x,y)的坐标会变成(cosα*x - sinα*y , sinα*x + cosα*y)。

有了以上两个东西这题就解辣
明显点(x,y)逆时针旋转45度坐标值放大sqrt(2)倍后的坐标是(x-y,x+y)。
因而我们直接把所有点弄过去,分别求x,y的中位数便可。
然后转回来的点有两种:第1坐标都是整数那末直接输出便可。
第2坐标有不是整数的(即.5)我们需要判断floor(x),ceil(x),floor(y),ceil(y)任意组成的点的距离。
这个复杂度O(n)不怂。

你问我没有SPJ这题怎样做?

登陆main.edu.pl,弄到所有数据,求中位数的时候依照他的意思求,取左侧或右侧我忘了,答案坐标非整数判断的时候依照他的意思取终究答案(好像是横纵坐标最大)。

赶快来人写SPJ!

代码:

#include #include #include #include #include #include #define N 100100 #define eps 1e⑻ using namespace std; typedef long long ll; int n; ll sum; struct node { ll x,y,t; friend istream& operator >> (istream &_,node &a) {scanf("%lld%lld%lld",&a.x,&a.y,&a.t);sum+=a.t;return _;} }pt[N]; mapint>mx,my; int totx,toty; struct arr { ll val,num; }arrx[N],arry[N]; bool cmp(arr a,arr b) { return a.val5],yy[5]; int main() { #ifndef ONLINE_JUDGE freopen("mag.in","r",stdin); freopen("mag.out","w",stdout); #endif scanf("%d",&n); for(int i=1;i<=n;i++)cin>>pt[i]; for(int i=1;i<=n;i++) { ll x=pt[i].x-pt[i].y,y=pt[i].x+pt[i].y; if(!mx[x]) mx[x]=++totx,arrx[totx].val=x,arrx[totx].num=pt[i].t; else arrx[mx[x]].num+=pt[i].t; if(!my[y]) my[y]=++toty,arry[toty].val=y,arry[toty].num=pt[i].t; else arry[my[y]].num+=pt[i].t; } sort(arrx+1,arrx+totx+1,cmp); sort(arry+1,arry+toty+1,cmp); for(int i=1;i<=totx;i++)sumx[i]=sumx[i-1]+arrx[i].num; for(int i=1;i<=toty;i++)sumy[i]=sumy[i-1]+arry[i].num; int flag=0; if(!(sum&1))flag=1; sum>>=1; double midX=0,midY=0; int l=1,r=totx,ans=0; while(l<=r) { int mid=(l+r)>>1; if(sumx[mid]<=sum)ans=mid,l=mid+1; else r=mid-1; } if(flag) { if(sumx[ans]==sum)midX=arrx[ans].val; else midX=arrx[ans+1].val; }else midX=arrx[ans+1].val; l=1,r=toty,ans=0; while(l<=r) { int mid=(l+r)>>1; if(sumy[mid]<=sum)ans=mid,l=mid+1; else r=mid-1; } if(flag) { if(sumy[ans]==sum)midY=arry[ans].val; else midY=arry[ans+1].val; }else midY=arry[ans+1].val; double prex=(midX+midY)/2; double prey=(midY-midX)/2; if(prex-floor(prex)>eps||prey-floor(prey)>eps) { xx[1]=xx[2]=(ll)floor(prex),xx[3]=xx[4]=(ll)ceil(prex); yy[1]=yy[3]=(ll)floor(prey),yy[2]=yy[4]=(ll)ceil(prey); ll sum=-1,no; for(int i=1;i<=4;i++) { ll ret=0; for(int j=1;j<=n;j++) { ll tmpx=pt[j].x-xx[i],tmpy=pt[j].y-yy[i]; if(tmpx<0)tmpx=-tmpx;if(tmpy<0)tmpy=-tmpy; ret+=pt[j].t*(max(tmpx,tmpy)); } if(sum==-1||ret<=sum) {sum=ret,no=i;} } printf("%lld %lld ",xx[no],yy[no]); }else { printf("%lld %lld ",(ll)prex,(ll)prey); } }
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生