51Nod - 1117 聪明的木匠

51Nod - 1117 聪明的木匠

一位老木匠需要将一根长的木棒切成N段。每段的长度分别为L1,L2,......,LN(1 <= L1,L2,…,LN <= 1000,且均为整数)个长度单位。我们认为切割时仅在整数点处切且没有木材损失。

木匠发现,每一次切割花费的体力与该木棒的长度成正比,不妨设切割长度为1的木棒花费1单位体力。例如:若N=3,L1 = 3,L2 = 4,L3 = 5,则木棒原长为12,木匠可以有多种切法,如:先将12切成3+9.,花费12体力,再将9切成4+5,花费9体力,一共花费21体力;还可以先将12切成4+8,花费12体力,再将8切成3+5,花费8体力,一共花费20体力。显然,后者比前者更省体力。

那么,木匠至少要花费多少体力才能完成切割任务呢?

Input

第1行:1个整数N(2 <= N <= 50000)
第2 - N + 1行:每行1个整数Li(1 <= Li <= 1000)。

Output

输出最小的体力消耗。

Input示例

3
3
4
5

Output示例

19

题解:

  (1), 使用逆向思维,拿最短的和第二短的来拼接,

  (2), 使用priority_queue 来保存。

#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 50000 + 5; 

int n, num[MAXN]; 

int main(){

	int ans, sum, elem1, elem2;
	while(scanf("%d", &n) != EOF){
		priority_queue<int> q; 

		for(int i=0; i<n; ++i){
			scanf("%d", &num[i]); 

			q.push(-num[i]);
		}
		sum = 0; 

		elem1 = q.top(); q.pop();
		elem2 = q.top(); q.pop(); 

		sum -= (elem1 + elem2); 

		while(!q.empty()){
			q.push( (elem1 + elem2) );

			elem1 = q.top(); q.pop();
			if(q.empty()){
				break;
			}
			elem2 = q.top(); q.pop();
			sum -= (elem1 + elem2);
		}
		printf("%d\n", sum );
	}
	return 0;
}

  

时间: 2024-08-02 04:07:35

51Nod - 1117 聪明的木匠的相关文章

51nod 1117 聪明的木匠 (贪心)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1117 跟挑战程序书上例题一样,将要切割的n断木板,分别对应二叉树树的叶子节点,则切割的总开销为木板的长度×节点的深度,可以画图理解,那么最短的木板(L1)应当是深度最大的叶子节点之一,次短的板(L2)和它是兄弟节点,由一块长度是(L1+L2) 的木板切割而来,这样可以变成(n-1)块木板,然后递归求解到n==1. 书上贪心部分用的是O(n×n) 的算法 在这里会超时,需

51nod 1117 聪明的木匠 (哈夫曼树)

题目:传送门. 题意:中文题. 题解:就是构造一颗哈夫曼树,数据结构里的知识. #include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <algorithm> using namespace std; struct cmp { bool operator ()(long long &a,long long &b) { retu

聪明的木匠 (哈夫曼树)

假设有n个权值,则构造出的哈夫曼树有n个叶子结点. n个权值分别设为 w1.w2.….wn,则哈夫曼树的构造规则为[1]: (1) 将w1.w2.…,wn看成是有n 棵树的森林(每棵树仅有一个结点): (2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左.右子树,且新树的根结点权值为其左.右子树根结点权值之和: (3)从森林中删除选取的两棵树,并将新树加入森林: (4)重复(2).(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树. 51nod 1117 #include

51Nod - 1067 Bash游戏 V2

51Nod - 1067 Bash游戏 V2 有一堆石子共有N个.A B两个人轮流拿,A先拿.每次只能拿1,3,4颗,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N,问最后谁能赢得比赛. 例如N = 2.A只能拿1颗,所以B可以拿到最后1颗石子. Input 第1行:一个数T,表示后面用作输入测试的数的数量.(1 <= T <= 10000) 第2 - T + 1行:每行1个数N.(1 <= N <= 10^9) Output 共T行,如果A获胜

51nod水题记

妈呀51nod已经刷不动了又开始跟bzoj一样总是得看题解了...那么发一下总结吧... 1051:最大子矩阵 #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t

51Nod 1072 威佐夫游戏

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1072 有2堆石子.A B两个人轮流拿,A先拿.每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取.拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出2堆石子的数量,问最后谁能赢得比赛. 例如:2堆石子分别为3颗和5颗.那么不论A怎样拿,B都有对应的方法拿到最后1颗. Input 第1行:一个数T,表示后面用作输入测试

51Nod 1069 Nim游戏 (位运算)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1069 有N堆石子.A B两个人轮流拿,A先拿.每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N及每堆石子的数量,问最后谁能赢得比赛. 例如:3堆石子,每堆1颗.A拿1颗,B拿1颗,此时还剩1堆,所以A可以拿到最后1颗石子. Input 第1行:一个数N,表示有N堆石子.(

51nod 1201 整数划分(dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1201 题解:显然是一道dp,不妨设dp[i][j]表示数字i分成j个一共有几种分法. 那么转移方程式为: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] 表示将i - 1划分为j个数,然后j个数都+1 还是不重复,将i - 1划分为j - 1个数,然后j - 1个数都+1,再加上1这个数. 然后就是j的范围要知道1+2+

2015第15周五寻找身边聪明的人

一般眼神活泼.动得快,说明此人喜欢用脑并在一刻不停地用着脑子,会让人比较聪明.更具体的可以有六个标准,两两一组分为基础指标,现实指标,和高层指标三个类别.基础.现实.高层的分类不是想说明轻重和高低,只是为了方便大家理解. 基础指标的第一个标准,是元认知(Metacognition)能力. 元认知能力,就是“对于认知的认知”和“关于知识的知识”,简单来说就是对于自我的认知过程的思考.关于元认知,网上有不少资料,大家可以通过搜索引擎找一下通俗的材料,感兴趣的也可以找相关的心理学文献读一下. 具有强元