PATグレードA 1046最短距離(20ポイント)(質問+コード+詳細コメント+最後のテストポイントのタイムアウト分析)

タスクは非常に単純です。単純なサイクルを形成する高速道路のN個の出口がある場合、出口のペア間の最短距離を伝える必要があります。

入力仕様:

各入力ファイルには1つのテストケースが含まれています。いずれの場合も、最初の行には整数N([3,10_ 5]内)が含まれ、その後にN整数の距離D 1 D 2⋯D Nが続きます。ここで、D iはi番目と(i + 1)番目の出口の間の距離であり、D NはN番目と1番目の出口の間です。行内のすべての数値はスペースで区切られています。2番目の行は正の整数M(≤10_4)を示し、M行が続き、出口に1からNまでの番号が付けられている場合、それぞれに出口番号のペアが含まれます。総往復距離がは10 7以下です。

出力仕様:

各テストケースについて、結果をM行で出力します。各行には、対応する特定の出口のペア間の最短距離が含まれています。

入力例:

5 1 2 4 14 9
3
1 3
2 5
4 1

出力例:

3
10
7

//この質問の意味は、円にn個の点があることです。任意の2点間の最小距離を見つけます。なぜ最小距離があるのですか?リング上ではa-> bなので、時計回りまたは反時計回りになり、移動距離が異なる場合があります。計算方法は比較的簡単です。距離を時計回り(反時計回り)に計算し、円の円周の半分と比較できます。円周の半分未満の場合、距離は希望の距離です。それ以外の場合は、円周マイナスです。距離。これは最も単純なシミュレーションですが、2つのポイントを取得するたびに1つずつ距離を合計すると、問題のデータがn max 1e5、m max 1e4であることに注意してください。ピットを踏んだ)解決策は、Diを読み取るときに(i + 1)番目のポイントから最初のポイント(No. 1)までの距離dis [i + 1]を見つけることです。a-> bからの距離を見つけるときは、disを計算するだけです。 [b] -dis [a]で十分です。O(1)の複雑さで、タイムアウトはありません以下に2種類のコードを示します。

法一:结果超时
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005];
int main() {
	int n, sum = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum += a[i];      //求出圆的周长
	}
	int m, k;
	k = sum / 2;         
	scanf("%d", &m);
	while (m--) {
		int x, y;
		scanf("%d%d", &x, &y);
		if (x > y)        //默认是(x, y),所以当读入的x > y时,就交换x, y
			swap(x, y);       //初用C++,原来algorithm头文件里面有swap函数,就不用自己写了
		int sum0 = 0;           //sum0是x -> y的距离,初始为0
		for (int i = x; i < y; i++)
			sum0 += a[i];
		printf("%d\n", sum0 < k ? sum0 : sum - sum0);
	}

	return 0;
}

 

//法二:AC了
#include<cstdio>
#include<algorithm>
using namespace std;

int a[100005], dis[100005];     //dis记录每个点到初始点(1号)的距离

int main() {
	int n, sum = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum += a[i];
		dis[i + 1] = sum;         //因为是记录到第一个点的距离,就从第二个点开始,所以下标为 i + 1
	}
	int m, k;
	k = sum / 2;
	scanf("%d", &m);
	while (m--) {
		int x, y;
		scanf("%d%d", &x, &y);
		if (x > y)
            swap(x, y)
		int sum0 = dis[y] - dis[x];         //直接求出两点之间的距离
		printf("%d\n", sum0 < k ? sum0 : sum - sum0);
	}
		
	return 0;
}

//何日も経って、Fa 2の考え方が前置和だと気づきました!

おすすめ

転載: blog.csdn.net/qq_45472866/article/details/104434994