http://hihocoder.com/contest/msbop2015qual/problem/3
O(n)的时间和空间开销
看似是图论,实际是数论。
关键点1:基站 “欧几里得距离的平方” 优先级远大于 “ 曼哈顿距离” 只需考虑欧几里德距离平方最小的坐标即可
关键点2:欧几里德距离平方,x轴y轴可分离讨论。变成两个 “一维上到各点欧几里德平方和最小的点”
∑[(Xn-X0)2+(Yn-Y0)2]=∑(Xn-X0)2+∑(Yn-Y0)2
关键点3:“一维上到各点欧几里德平方和最小的点” =》 ∑(xn-x0)2 =Σ(Xn2)+nX0 - 2X0 ∑(Xn) 最小
问题变成,求二元一次方程组最小解的横坐标
最后:
X0= ∑(Xn)/n;
Y0= ∑(Yn)/n;
(因为要求 “通讯基站仅必须建立在格点上” 所以需要对最近的四个点进行判定(x+y)(x,y+1)(x+1,y)(x+1,y+1))
然后 “ 最小曼哈顿距离”的时候,xy是不可分离的,但因为关键点1 也只需要对上面四个点遍历一次就可以获得最终解
80行代码 出去头尾声明引用,中间的空行,可能也就60+行
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <vector> 5 #include <math.h> 6 using namespace std; 7 #define modnum 100007 8 long long cost=0; 9 long long maxll=9223372036854775807; 10 long long mincost=maxll; 11 long long totalAx=0; 12 long long totalAxSquare=0; 13 long long totalAy=0; 14 long long totalAySquare=0; 15 vector<long long> bx; 16 vector<long long> by; 17 int N,M,A,B;
18 long long cal(long long totalSquare,long long total,long long x,long long num) 19 { 20 long long ans=0; 21 ans+=totalSquare+num*x*x-2*total*x; 22 return ans; 23 } 24 long long calAll(long long x,long long y) 25 { 26 long long ans=maxll; 27 for(int i=0;i<bx.size();i++) 28 { 29 ans=min(ans,abs(bx[i]-x)+abs(by[i]-y)); 30 } 31 return ans+cal(totalAxSquare,totalAx,x,A)+cal(totalAySquare,totalAy,y,A); 32 } 33 int main() 34 { 35 36 int T=0; 37 int Case=0; 38 cin>>T; 39 while(T) 40 { 41 bx.clear(); 42 by.clear(); 43 totalAx=0; 44 totalAxSquare=0; 45 totalAy=0; 46 totalAySquare=0; 47 48 T--; 49 Case++; 50 51 cin>>N>>M>>A>>B; 52 int temp=0; 53 for(int i=0;i<A;i++) 54 { 55 cin>>temp; 56 totalAx+=temp; 57 totalAxSquare+=temp*temp; 58 cin>>temp; 59 totalAy+=temp; 60 totalAySquare+=temp*temp; 61 } 62 for(int i=0;i<B;i++) 63 { 64 cin>>temp; 65 bx.push_back(temp); 66 cin>>temp; 67 by.push_back(temp); 68 } 69 long long x,y; 70 x=totalAx/A; 71 y=totalAy/A; 72 long long ans=maxll; 73 ans=min(ans,calAll(x,y)); 74 ans=min(ans,calAll(x,y+1)); 75 ans=min(ans,calAll(x+1,y)); 76 ans=min(ans,calAll(x+1,y+1)); 77 78 cout<<"Case #"<<Case<<": "<<ans<<endl; 79 } 80 }
以上代码有个问题。。
第52行 int temp=0;
int在大数据的时候10^7的数据大小是可以正常输入的
但,第57 60行,temp*temp直接导致数据溢出了。。
以下是通过大数据的算法 其实就是把int temp 改成了long long temp
以下代码已通过大数据测试
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <vector> 5 #include <math.h> 6 using namespace std; 7 #define modnum 100007 8 long long cost=0; 9 long long maxll=9223372036854775807; 10 long long mincost=maxll; 11 long long totalAx=0; 12 long long totalAxSquare=0; 13 long long totalAy=0; 14 long long totalAySquare=0; 15 vector<long long> bx; 16 vector<long long> by; 17 int N,M,A,B; 18 long long cal(long long totalSquare,long long total,long long x,long long num) 19 { 20 long long ans=0; 21 ans+=totalSquare+num*x*x-2*total*x; 22 return ans; 23 } 24 long long calAll(long long x,long long y) 25 { 26 long long ans=maxll; 27 for(int i=0;i<bx.size();i++) 28 { 29 ans=min(ans,abs(bx[i]-x)+abs(by[i]-y)); 30 } 31 return ans+cal(totalAxSquare,totalAx,x,A)+cal(totalAySquare,totalAy,y,A); 32 } 33 int main() 34 { 35 36 int T=0; 37 int Case=0; 38 cin>>T; 39 while(T) 40 { 41 bx.clear(); 42 by.clear(); 43 totalAx=0; 44 totalAxSquare=0; 45 totalAy=0; 46 totalAySquare=0; 47 48 T--; 49 Case++; 50 51 52 cin>>N>>M>>A>>B; 53 long long ans=maxll; 54 long long temp=0; 55 for(int i=0;i<A;i++) 56 { 57 cin>>temp; 58 totalAx+=temp; 59 totalAxSquare+=temp*temp; 60 cin>>temp; 61 totalAy+=temp; 62 totalAySquare+=temp*temp; 63 } 64 for(int i=0;i<B;i++) 65 { 66 cin>>temp; 67 bx.push_back(temp); 68 cin>>temp; 69 by.push_back(temp); 70 } 71 long long x,y; 72 x=totalAx/A; 73 y=totalAy/A; 74 ans=min(ans,calAll(x,y+1)); 75 ans=min(ans,calAll(x+1,y)); 76 ans=min(ans,calAll(x+1,y+1)); 77 ans=min(ans,calAll(x,y)); 78 79 cout<<"Case #"<<Case<<": "<<ans<<endl; 80 } 81 }