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-x02  =Σ(Xn2)+nX- 2X∑(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 }

 

posted on 2015-04-18 00:10  海暗  阅读(1526)  评论(4编辑  收藏  举报