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 D1D2⋯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:
1 2 3 4 5
5 1 2 4 14 9 3 1 3 2 5 4 1
Sample Output:
1 2 3
3 10 7
题解
思路
题目的意思是,有一些环形站点,给你这几个站点和邻居之间的距离
然后给你两个站点编号,求它们的最近距离
很多种方法
一种是顺着思路,正着搜一遍,反着搜一遍。遇到列表尾巴了就移到0,相当于环形了。优点是直观方便。
一种是,直接把原来的距离数组复制一遍,然后就搜两次,一次从原来的begin和end搜,一次搜end到distance + begin 的距离。优点是代码少。缺点是空间复杂度高且算法没什么本质上的卵用。
distance = list(map(int, input().split()[1:])) distance = distance + distance i = int(input()) for _ in range(i): start, end = list(map(lambda x: int(x) - 1, input().split())) if start > end: start,end = end,start print(min(sum([distance[i] for i in range(start, end)]), sum([distance[i] for i in range(end, len(distance)//2 + start)])))
distance = list(map(int, input().split()[1:])) i = int(input()) for _ in range(i): start, end = list(map(lambda x: int(x) - 1, input().split())) i = start sum = 0 while i != end: sum += distance[i] i += 1 if i == len(distance): i = 0 i = end sum2 = 0 while i != start: sum2 += distance[i] i += 1 if i == len(distance): i = 0 print(min(sum, sum2))
动态规划法
会有一个点超时。
1 2 3 4 5 6 7 8 9 10 11 12
dis = list(map(int, input().split()[1:])) dp = [[0for _ in range(len(dis))] for _ in range(len(dis))] for i, j in enumerate(dis): dp[i][(i + 1) % len(dis)] = j for i in range(2, len(dp)): for j in range(len(dp)): dp[j][(j + i) % len(dis)] = dp[j][(j + i - 1) % len(dis)] + dp[(j + i - 1) % len(dis)][(j + i) % len(dis)] i = int(input()) for _ in range(i): a, b = list(map(int, input().split())) print(min(dp[a-1][b-1], dp[b-1][a-1]))
求和列表法 Python
最终方法。但是Python还是会超时,建议使用C++。
1 2 3 4 5 6 7 8 9 10
dis = list(map(int, input().split()[1:])) num = len(dis) _sum = [sum(dis[:i]) for i in range(num + 1)] i = int(input()) for _ in range(i): a, b = list(map(lambda x: int(x) - 1, input().split())) if a > b: a, b = b, a print(min(_sum[b] - _sum[a], _sum[-1] - _sum[b] + _sum[a]))
intmain(){ int num_exits; scanf("%d",&num_exits); int sum[num_exits + 1]; sum[0] = 0; for (int i = 1; i <= num_exits; i++) { scanf("%d", &sum[i]); sum[i] += sum[i-1]; } int num_que; scanf("%d", &num_que); for (int i = 0; i < num_que; i++) { int a, b; scanf("%d %d", &a, &b); if (a > b) swap(a, b); printf("%d\n", min(sum[b-1] - sum[a-1], sum[num_exits] - sum[b-1] + sum[a-1])); } }