题目描述:
给定一段一段的绳子,你需要把它们串成一条绳。每次串连的时候,是把两段绳子对折,再如下图所示套接在一起。这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连。每次串连后,原来两段绳子的长度就会减半。
给定N段绳子的长度,你需要找出它们能串成的绳子的最大长度。
输入格式:
每个输入包含1个测试用例。每个测试用例第1行给出正整数N (2 <= N <= 104);第2行给出N个正整数,即原始绳段的长度,数字间以空格分隔。所有整数都不超过104。
输出格式:
在一行中输出能够串成的绳子的最大长度。结果向下取整,即取为不超过最大长度的最近整数。
输入样例:8 10 15 12 3 4 13 1 15输出样例:
14
题目分析:
每加入一段绳子,最新的长度=(之前的绳子长度+刚加入的绳子长度)/2,表明最先加入的绳子,被对折的次数越多。如果之前加入的绳子比较长,可以想到,就有越多次的对折点发生在这根绳子上。因此应该先挑当前最短的加入进去。那么很容易想到对读入的所有绳段长度进行非递减排序。代码如下:
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=10001;
int main()
{
int n,num[maxn];
scanf("%d",&n); //读入绳段数
for(int i=0;i<n;i++){
scanf("%d",&num[i]); //读入每一段的长度
}
sort(num,num+n);
int maxlen=num[0]; //maxlen的初始长度是最小的那一段,不能是零,因为这样在下面的循环中就相当与最小的那一段多折了一次
for(int i=1;i<n;i++){
maxlen=(maxlen+num[i])/2;
}
printf("%d",maxlen); //输出最大长度。
return 0;
}