1070 结绳 (25 分)
题意描述:
给定一段一段的绳子,你需要把它们串成一条绳。每次串连的时候,是把两段绳子对折,再如下图所示套接在一起。这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连。每次串连后,原来两段绳子的长度就会减半。

给定 N 段绳子的长度,你需要找出它们能串成的绳子的最大长度。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出正整数 N (2≤N≤10^4 );第 2 行给出 N 个正整数,即原始绳段的长度,数字间以空格分隔。所有整数都不超过10^4 。
输出格式:
在一行中输出能够串成的绳子的最大长度。结果向下取整,即取为不超过最大长度的最近整数。
输入样例:
8
10 15 12 3 4 13 1 15
输出样例:
14
解题思路:
Alice: 没思路啊,(¦3」∠)
Bob:(¦3」∠) 我也没思路啊。
Alice: 这个样例是怎么算出来的呢??
Bob: 读题读题,书读百遍其义自见。折叠。。折叠,长度减半。会不会是贪心呐?
Alice: 贪心?? 如果我们从最后的角度来看。其实 最终的长度 S = K1 * S1 + K2 * S2 + ... Kn * Sn K1, K2, Kn 都是 2 的幂 的 倒数。 怎么让这个和最大呢 ? 让 S1, S2, Sn 中较大的值有较大的系数啊。越大的系数对应着越晚被折叠,越小的系数意味着越早被折叠。
Bob: 我明白了!,就让较短的绳子先参与折叠,这样损失就是最小的,最先参与折叠的那两段绳子被折叠的次数最多,最后被加上去的绳子,折叠次数最少只有一次。
Alice: 这就是贪心?
Bob: 这就是贪心。
代码:
- Alice’s Python Version :
def main():
N = int(input())
data = [int(x) for x in input().split()]
data.sort()
# 从小到大排序
length = float(data[0])
# 从小到大 贪心 越小的绳子 折叠次数越多, 损失在折叠中的长度越小
for x in range(1, len(data)):
length = (length + data[x]) / 2.0
print(int(length))
if __name__ == '__main__':
main()
- Bob’s C++ Version :
#include <iostream>
#include <algorithm>
#define NN 10000 + 10
using namespace std;
int main(){
int N, data[NN];
cin >> N;
for(int i=0; i<N; ++i){
cin >> data[i];
}
sort(data, data + N);
// 排序,参数分别是起始位置和终止位置,默认升序。
float answer = data[0];
for(int i=1; i<N; ++i){
answer = (answer + data[i]) / 2;
}
cout << int(answer) << endl;
return 0;
}
易错点:
- 向下取整 ?? 可以用强制类型转换啊,float 转 int 直接去掉小数部分。 什么?你说会不会存不下,10 ^ 4 * 10 ^ 4 才 10 ^ 8 , 32 位的整数都存的下, 32 位的浮点肯定也存的下。
总结:
| Python Run time | C++ run time |
|---|---|
![]() | ![]() |
For relax :




57

被折叠的 条评论
为什么被折叠?



