问题 E: Shortest Distance (20)
第一次的想法码的代码如下(超时):
1 #include <iostream> 2 #include<cstring> 3 #include<vector> 4 #define maxn 100001 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 using namespace std; 7 int n; 8 typedef struct Dnode{ 9 int s; 10 int e; 11 int d; 12 }Dnode; 13 14 Dnode Dset[maxn]; 15 int p1,p2; 16 void solve(){ 17 int sum1=0; 18 int min; 19 int s=p1; 20 int e=p2; 21 while(s!=e){ 22 sum1+=Dset[s].d; 23 s=Dset[s].e; 24 } 25 min=sum1; 26 sum1=0; 27 28 while(s!=p1){ 29 sum1+=Dset[s].d; 30 s=Dset[s].e; 31 } 32 if(min<sum1) cout<<min<<endl; 33 else cout<<sum1<<endl; 34 35 } 36 int main(int argc, char** argv) { 37 int n; 38 int i; 39 int d; 40 int t; 41 int j; 42 int test; 43 Dnode pa; 44 while(cin>>n){ 45 t=1; 46 for(i=1;i<=n;i++){ 47 cin>>d; 48 j=i+1; 49 if(j>n) j%=n; 50 Dset[t].s=i; 51 Dset[t].e=j; 52 Dset[t].d=d; 53 t++; 54 } 55 56 cin>>test; 57 while(test--){ 58 cin>>p1>>p2; 59 solve(); 60 } 61 62 } 63 return 0; 64 }
上面的代码时间超时
第二次优化一下,还超时:
代码如下:
1 #include <iostream> 2 #include<cstring> 3 #include<vector> 4 #define maxn 100001 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 using namespace std; 7 int n; 8 typedef struct Dnode{ 9 int s; 10 int e; 11 int d; 12 }Dnode; 13 14 Dnode Dset[maxn]; 15 int p1,p2; 16 int total_d; 17 void solve(){ 18 int sum1=0; 19 int min; 20 int s=p1; 21 int e=p2; 22 while(s!=e){ 23 sum1+=Dset[s].d; 24 s=Dset[s].e; 25 } 26 min=sum1; 27 sum1=total_d-min; 28 if(min<sum1) cout<<min<<endl; 29 else cout<<sum1<<endl; 30 31 } 32 int main(int argc, char** argv) { 33 int n; 34 int i; 35 int d; 36 int t; 37 int j; 38 int test; 39 Dnode pa; 40 while(cin>>n){ 41 t=1; 42 total_d=0; 43 for(i=1;i<=n;i++){ 44 cin>>d; 45 total_d+=d; 46 j=i+1; 47 if(j>n) j%=n; 48 Dset[t].s=i; 49 Dset[t].e=j; 50 Dset[t].d=d; 51 t++; 52 } 53 54 cin>>test; 55 while(test--){ 56 cin>>p1>>p2; 57 solve(); 58 } 59 60 } 61 return 0; 62 }
暂时还没想到哪可以优化,不过我估摸着,得预先把每个点的最小值弄出来,因为M最大为10^4,而N最大为10^6 M*N=10^10 严重超时!
如果我能预先把它算出来的话最大的复杂度为O(10^4)
13:37:20 2019-03-30
第三次写:
值得注意的是对于二维数组长度不能超过10000,否则会报错的!而且提交上去,会编译错误! 如果你改小数组大小,回报出运行错误!
后来想,我保存一下每一组的最大值不就行了?结果发现不行,因为二维数组太大了!
由于数组大小太小而运行出错的代码如下:
1 #include <iostream> 2 #include<cstring> 3 #include<vector> 4 #define maxn 10001 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 using namespace std; 7 int n; 8 int min_d[maxn][maxn];//存储i->j的最短距离 9 10 typedef struct Dnode{ 11 int s; 12 int e; 13 int d; 14 }Dnode; 15 16 Dnode Dset[maxn]; 17 int p1,p2; 18 int total_d; 19 void solve(){ 20 int sum1=0; 21 int min; 22 int s=p1; 23 int e=p2; 24 while(s!=e){ 25 sum1+=Dset[s].d; 26 s=Dset[s].e; 27 } 28 min=sum1; 29 sum1=total_d-min; 30 if(min>sum1) 31 min=sum1; 32 min_d[p1][p2]=min_d[p2][p1]=min; 33 cout<<min<<endl; 34 } 35 int main(int argc, char** argv) { 36 int n; 37 int i; 38 int d; 39 int t; 40 int j; 41 int test; 42 43 while(cin>>n){ 44 t=1; 45 total_d=0; 46 memset(min_d,0,sizeof(min_d)); 47 for(i=1;i<=n;i++){ 48 cin>>d; 49 total_d+=d; 50 j=i+1; 51 if(j>n) j%=n; 52 Dset[t].s=i; 53 Dset[t].e=j; 54 Dset[t].d=d; 55 t++; 56 } 57 58 cin>>test; 59 while(test--){ 60 cin>>p1>>p2; 61 if(min_d[p1][p2]!=0) 62 cout<<min_d[p1][p2]<<endl; 63 else 64 solve(); 65 } 66 67 } 68 return 0; 69 }
于是我又想,二维数组不行,那一位数组保存不就行了?
想到这个我就想到了一个东西:
思考一下:如果我知道d12 、d13 、d14 、d15 的距离,是不是能求出任意两点的距离呢?肯定能求出
dij=d1j-d1i (*)
一旦你想到了(*)式,你就离正确的答案不远了!
于是我就设了一个数组 d_total[maxn] ,其中
d_total[2] 表示从1-2的距离
d_total[3] 表示 1-3的距离
.....
d_total[5] 表示1-5的距离
.....
还能优化的是:假如你求出的dij大于半个圆的长度,那最短的就是 : 这个圆的周长-dij
如图所示:

看完这个图片,应该是很清楚了,话不多说,代码如下
AC了的代码:
1 #include <iostream> 2 #include<cstring> 3 #include<vector> 4 #define maxn 100001 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 using namespace std; 7 8 int d_total[maxn]; 9 /*d_total[2] 表示从1-2的距离 10 d_total[3] 表示 1-3的距离 11 ..... 12 d_total[5] 表示1-5的距离 13 */ 14 15 16 int p1,p2; 17 int n;//它在main函数里面的话,n会为0 18 void solve(){ 19 int d; 20 d=d_total[p2]-d_total[p1]; //因为我默认是1为起点的 21 if(d<d_total[n+1]/2) cout<<d<<endl; 22 else cout<<d_total[n+1]-d<<endl; 23 } 24 int main(int argc, char** argv) { 25 26 int i; 27 int d; 28 int t; 29 int j; 30 int test; 31 32 while(cin>>n){ 33 t=2; 34 35 36 for(i=1;i<=n;i++){ 37 cin>>d; 38 d_total[t]+=d_total[t-1]+d; 39 t++; 40 41 } 42 43 int temp; 44 cin>>test; 45 while(test--){ 46 cin>>p1>>p2; 47 if(p1>p2){//因为在solve()函数中我默认p2是大于p1的,而题目给的不一定,所以要交换 48 temp=p1; 49 p1=p2; 50 p2=temp; 51 } 52 53 solve(); 54 } 55 56 } 57 return 0; 58 }
我想多说一句:通过这道题我感受到了优化的魅力和算法的魅力.所以,当我们对一道题可能弄不出来的时候,不要轻易去看答案,而是要自己独立思考!总会做出来的!代码是朋友...