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 }