【蓝桥杯基础练习】1700:Crossing river

题目来源:北京大学程序在线评测系统POJ
1700:Crossing River

题目

Crossing River

A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arrangement must be arranged in order to row the boatback and forth so that all people may cross. Each person has a different rowing speed; the speed of a couple is determined by the speed of the slower one. Your job is to determine a strategy that minimizes the time for these people to get across.

题目要求

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains N, and the second line contains N integers giving the time for each people to cross the river. Each case is preceded by a blank line. There won’t be more than 1000 people and nobody takes more than 100 seconds to cross.

Output

For each test case, print a line containing the total number of seconds required for all the N people to cross the river.

测试样例

Sample Input

1
4
1 2 5 10

Sample Output

17

#include<stdio.h>
#define N 100
int sum=0;
static int temp=1;
void calculate(int a[N],int b[N],int n,int min,int i,int j,int k)
{
    
    
	int d,c;
	if(i%2==0)
	{
    
    
		c=0;
		k=0;
		j=temp;//首轮循环时等于1,下一轮时等于上一轮的值
		sum=sum+a[i];//sum等于原值+未过河的两个值中的最大值(过河时间取决于耗费最长时间的人)
		b[j++]=a[i-1];//b从1开始,记录过河的值
		b[j++]=a[i];
		temp=j;//用temp记录下j的值,以便下一轮赋值给j
		a[i-1]=-1;//过河了的数全部变为-1
		a[i]=-1;
		while(b[k]<=0)//检查右边的数组,当出现小于等于0的数时,跳出
			k++;
		min=b[k];//将其值赋值给min
		d=k;//用一个变量记录最小值时,最小值数组下标
		for(k;k<=n;k++)
		{
    
    
			if(b[k]>0&&b[k]<min)//如果仍有大于0且小于最小值的数
			{
    
    
				min=b[k];//重新记录min值
				d=k;//重新记录min值数组下标
			}
		}
		sum=sum+min;//sum再加上这个最小值
		b[d]=-1;//将最小值所在位置的值变为-1(设这个最小值过河)
		while(a[c]!=-1)//当a数组中的值为-1时候,不断循环c
			c++;//c不断++,最后跳出
		a[c]=min;//将最小值赋值至这个位置
	}
}
int main()
{
    
    
	int z,n,k,i,j=1,min,max,y;
	scanf("%d",&z);//输入测试组数
	if(z<=0||z>20) //限制条件
		return 0;
	for(y=0;y<z;y++)//循环条件
	{
    
    
		scanf("%d",&n);//输入不同的速度个数
		int a[N],f[3];
		int b[N],e[2];
		for(i=1;i<=n;i++)//输入不同的速度
			scanf("%d",&a[i]);
		if(n%2==0)//如果个数为偶数
		{
    
    
			for(i=1;i<=n;i++)//在1—n的情况下执行这个函数(e.g 1 2 5 10,此处计算出两次过河,在未过河一边的只剩下一种情况)
				calculate(a,b,n,min,i,j,k);
			k=0;
			for(i=1;i<=n;i++)//检测在未过河一边未过河的人的速度
			{
    
    
				if(a[i]!=-1&&a[i]!=' ')//限制条件
				{
    
    
					e[k]=a[i];//若不为0,赋值给e[k],未过河一边只会有两个人
					k++;
				}
			}
			if(e[0]<e[1])//判断出最大值后加在sum上
				sum=sum+e[1];
			else if(e[1]<=e[0])
				sum=sum+e[0];
			temp=0;//temp置0,以进行第二轮计算
		}
		else if(n%2!=0)//个数为奇数
		{
    
    
			int temp1=0;
			for(i=1;i<=n-1;i++)//同上理
				calculate(a,b,n,min,i,j,k);
			for(i=1;i<=n;i++)//同上理,但是此时未过河一边有3个数
				if(a[i]>0)
				{
    
    
					f[temp1]=a[i];
					temp1++;
				}
				max=f[0];
			for(j=0;j<2;j++)//加上最大值和次最大值
				for(i=0;i<3;i++)//未过河的三个数中,加上最大值
				{
    
    
					if(f[i]>max&&f[i]>0)
					{
    
    
						max=f[i];
						sum=sum+f[i];
						f[i]=-1;
					}
				}
			for(i=0;i<3;i++)//加上最后过河的值
				if(f[i]!=-1)
					sum=sum+f[i];
			temp=0;//temp置0,以进行第二轮计算
	}
	printf("%d\n",sum);
	sum=0;//将sum置0,以进行第二轮计算
	}
	return 0;
}

运行结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/passer__jw767/article/details/108740061