PAT甲级真题及训练集(1)--1046. Shortest Distance (20)

1046. Shortest Distance (20)

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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 1
Sample Output:
3
10
7
方案1:采用链表的方式
/**
作者:一叶扁舟
时间:22:04 2017/6/16
思路:最初的想法是,采用双向的循环链表来做,无论顺时针还是逆时针,链表都可以访问,同时可以将所走的路径
	给打印出来,但是题目中并没有说要输出所走的路径,所以后来发现用链表更加麻烦了,并且最终时间超时了
	在这里只是说提供解决问题的一种方案,虽然这个方案并不完美
*/
#include <stdio.h>
#include <stdlib.h>
#define maxSize 100001

//方法1,使用双向链表
struct Data{
	int num;//位置序号
	int distance;//顺时针距离
//	struct Data *pre;//前驱
	struct Data *next;
};
//获取最短距离
void getDistance(struct Data *head,int start ,int end,int *result){
	struct Data *p = head;
	int d = 0;
	//找到start位置
	while (p->num != start){
		p = p->next;
	}
	 
	while (p->num != end){
		d = d + p->distance;
		p = p->next;
	}
	*result = d;
}
//测试结果正确,但是运行超时
int main(){
	int N;
	int testNum;
	int dis;//控制台中的长度
	struct Data *head,*p;
	struct Data *pCurrent;
	int sum = 0;
	head = (struct Data *)malloc(sizeof(struct Data));
	pCurrent = head;
	p = head;
	scanf("%d",&N);
	for (int i = 0; i < N; i++){
		scanf("%d",&dis);
		sum += dis;
		struct Data *temp = (struct Data *)malloc(sizeof(struct Data));
		temp->num = i;
		temp->distance = dis;
		pCurrent->next = temp;
		pCurrent = temp;
	}
	//形成一个循环链表
	pCurrent->next = head ->next;

	//输入的测试用例组数
	scanf("%d", &testNum);
	int start, end;
	for (int i = 0; i < testNum; i++){
		//计算从strat 到end的距离
		scanf("%d%d",&start,&end);
		int result;
		if (start > end){
			getDistance(head->next, end - 1, start - 1, &result);
		}
		else{
			getDistance(head->next,start-1,end -1,&result);
		}
		//输出结果
		if (result < (sum - result)){
			printf("%d\n", result);
		}
		else{
			printf("%d\n", sum - result);
		}
	}

	
	return 0;
}


方案2:采用数组:
/*
作者:一叶扁舟
时间:9:28 2017/6/17
思路:使用该方法,和使用循环链表类似,在pat测试结果是运行结果正确,但是时间超时
*/
#include <stdio.h>
#include <stdlib.h>
#define maxSize 100001

//从start点到end点的距离
void getDistance2(int *data,int N, int start, int end,int *result){
	int distance = 0;
	for (int i = start; i < end; i++){
		distance += data[i];
	}
	*result = distance;
}

int main(){
	int N;//定点个数
	int testTime;//测试案例的次数
	int data[maxSize];//相邻两个定点的距离
	int a, b;
	int sum = 0;
	scanf("%d", &N);
	for (int i = 0; i < N; i++){
		scanf("%d",&data[i]);
		sum += data[i];
	}
	scanf("%d",&testTime);
	for (int i = 0; i < testTime; i++){
		scanf("%d%d", &a, &b);
		int result;
		if (a > b){
			getDistance2(data, N, b - 1, a - 1,&result);
		}
		else{
			getDistance2(data, N, a - 1, b - 1, &result);
		}
	//输出最小距离
		if (result < sum - result){
			printf("%d\n",result);
		}
		else{
			printf("%d\n",sum - result);
		}
	}

	system("pause");
	return 0;
}

方案3:采用静态数组,时间复杂度为O(1),最优解,对于遇到时间差,距离差类似题目都可以采用静态数组的方式,在程序运行之前就将所有的数据都计算好。
/*
作者:一叶扁舟
时间:10:23 2017/6/17
思路:利用静态数组,用一个数组装所有定点到1位置的距离,如果求两点距离直接用两点值相减即可
时间复杂度为O(1)
*/
#include <stdio.h>
#include <stdlib.h>
#define maxSize 100001

int main(){
	int N; 
	int testTime;
	int data[maxSize] = { 0 };
	int a, b;
	int dis;//相邻两个定点的距离
	int sum = 0;
	scanf("%d",&N);
		data[0] = 0;
	for (int i = 1; i <= N; i++){
		scanf("%d",&dis);
		sum += dis;
		data[i] = data[i - 1] + dis;
	}
	scanf("%d",&testTime);
	for (int i = 0; i < testTime; i++){
		scanf("%d%d",&a,&b);
		if (a > b){//要保证定点a比定点b的序号要小
			int temp = b;
			b = a;
			a = temp;
		}
		int d = data[b - 1] - data[a - 1];
		if (d < sum - d){
			printf("%d\n",d);
		}
		else{
			printf("%d\n",sum - d);
		}
	}

	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值