The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.
Input Specification:
Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 ... DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (<=104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107.
Output Specification:
For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.
Sample Input:5 1 2 4 14 9 3 1 3 2 5 4 1Sample Output:
3 10 7
AC
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
int arr[100001];
int sum;
int main(){
scanf ( "%d" , &sum );
int t = 0,n = 0,a1,a2,dis_1 = 0,dis_2 = 0,temp;
for ( int i = 1; i <= sum; i++ ){
scanf("%d",&t);
arr[i] = t + arr[i-1];
}
scanf ( "%d" , &n );
for ( int i = 1; i <= n; i++ ){
dis_1 = 0,dis_2 = 0;
scanf("%d %d",&a1,&a2);
if ( a1 > a2 ){
temp = a1;
a1 = a2;
a2 = temp;
}
dis_1 = arr[a2 - 1] - arr[a1 - 1];
dis_2 = arr[sum] - dis_1;
dis_1>dis_2? printf("%d\n",dis_2): printf("%d\n",dis_1);
}
return 0;
}
思路:
一开始把两点之间的距离分别存储在数组下标中,例如D1 和 D2之间的距离,就存在arr[1]中,D2和D3的距离存在arr[2]中,依次类推,按题目中给的样例,假设总个数为5个点,那么arr[5]中保存的就是D5和D1 的距离。再给出点之后,按照两种不同方向计算两点之间不同的距离,比较出大小就可以得到结果了。这是第一种比较直观的想法,就是直接将两点距离保存,要计算的时候就按照不同的点来计算就好了。但是这样做存在问题,最后一个测试点会超时,因为可以从代码中看到重复计算的次数太多,计算D1和D2之间的距离时,计算一次,计算D1和D3之间距离时,又需要在计算一边D1和D2的距离,以此类推 重复计算太多。
思路2就是上面AC的代码,这个方法是将距离保存在数组中,但是保存的不是相邻两点距离,而是各个点之间累计的距离。这样做好处有2
第一点好处:避免重复计算
将距离保存在数组中,在计算距离的时候,直接用减法,省去每个点之间的距离相加
好处2:
计算两种距离的之后,第二种只需要用总距离减去第一种距离就可以了。而总距离就保存在数组的最后一个里面。
第一种思路的代码,最后一个测试点超时:
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
int arr[100001];
int sum;
/*
捋一下思路:
应该存在共性,就是一对数,距离有两种,一种是顺时针,一种是逆时针
顺时针逆时针所得到的距离大小不定
无论给出来的数是大数在前还是小数在前,都是以上这两种情况。
因此可以在做之前调整两个数的位置
*/
int main(){
scanf ( "%d" , &sum );
//t是临时输入的距离,用循环。n是后面待计算距离的个数
//a1,a2分别是输入的两个坐标
int t = 0,n = 0,a1,a2,dis_1 = 0,dis_2 = 0,temp;
for ( int i = 1; i <= sum; i++ ){
scanf("%d",&t);
arr[i] = t;
}
scanf ( "%d" , &n );
for ( int i = 1; i <= n; i++ ){
dis_1 = 0,dis_2 = 0;
scanf("%d %d",&a1,&a2);
/*
每一对数包含两种情况,长距离和短距离,分别存在dis_1和dis_2中,
最后要输出最短的距离
*/
//定大小,小的放在前面 ,a1小
if ( a1 > a2 ){
temp = a1;
a1 = a2;
a2 = temp;
}
//第一种距离dis_1 小顺时针---小顺时针其实是逆时针
for ( int i = a1; i <= a2 -1; i++ ){
dis_1 = dis_1 + arr[i];
}
//第二种距离dis_2 大顺时针
/*
这里有两种情况,一种是a1是1的时候,这种情况加到a5就不再循环
第二种情况:当a1比1大的时候,需要 从1开始继续循环到小的-1 ,分为两段计算
*/
//无论第一种第二种,这一段是必须算的距离
for ( int i = a2; i <= sum; i++ ){
dis_2 = dis_2 + arr[i];
}
for ( int i = 1; i<= a1 - 1; i++ ){
dis_2 = dis_2 + arr[i];
}
//第一种
/*
if ( a1 = 1 ){
dis_2 = dis_2;
}
//第二种
else{
}
*/
dis_1>dis_2? printf("%d\n",dis_2): printf("%d\n",dis_1);
}
return 0;
}