1070 结绳 (25 分)

1070 结绳 (25 分)

题意描述:

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

rope.jpg

给定 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 timeC++ run time
pythonc++

For relax :


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值