1. 程式人生 > 其它 >[PAT乙級]1070 結繩 (思路+精簡程式碼)

[PAT乙級]1070 結繩 (思路+精簡程式碼)

技術標籤:PAT乙級(C語言)

1070 結繩

給定一段一段的繩子,你需要把它們串成一條繩。每次串連的時候,是把兩段繩子對摺,再如下圖所示套接在一起。這樣得到的繩子又被當成是另一段繩子,可以再次對摺去跟另一段繩子串連。每次串連後,原來兩段繩子的長度就會減半。

在這裡插入圖片描述

給定 N 段繩子的長度,你需要找出它們能串成的繩子的最大長度。

輸入格式:
每個輸入包含 1 個測試用例。每個測試用例第 1 行給出正整數 N (2 ≤ N ≤ 104​​);第 2 行給出 N 個正整數,即原始繩段的長度,數字間以空格分隔。所有整數都不超過10​4​​ 。

輸出格式
在一行中輸出能夠串成的繩子的最大長度。結果向下取整,即取為不超過最大長度的最近整數。

輸入樣例:

8
10 15 12 3 4 13 1 15

輸出樣例:

14

思路:數學問題,越早使用的繩,後續要對摺的次數越多,也就變得越短,對於一根本來就很短的繩,對摺上百上千次,對最終結果影響不大;而對於一根原本很長的繩,若多次對摺,就會極大地影響最終所得繩子長度。
故本題的解法就是,將初始繩長按升序排序,由短到長地依次選擇,累計到總長度中。

#include <stdio.h>
#include <math.h>
#include <algorithm>
int main() {
	int n, a[10000] = { 0 };
	scanf("%d"
, &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); std::sort(a, a + n); double sum = a[0]; //單獨讓sum初始值為a[0],否則若下方i從0開始,將多對摺一次 for (int i = 1; i < n; i++) sum = (sum + a[i]) / 2; printf("%d", (int)sum); //向下取整,直接丟掉小數 return 0; }