第六天 大杂烩杂烩

描述

农夫约翰想修复牧场周围的一小部分篱笆。他测量围栏,并发现他需要Ñ(1≤ Ñ ≤20000)厚木板,每一个都具有一些整数长度大号我(1≤ 大号我 ≤50000)单元。然后,他购买了一块足够长的单块长板,足以切入N块木板(即,其长度为长度L i的总和)。FJ忽略了“锯缝”,即锯切时因锯末而损失的额外长度;您也应该忽略它。

FJ遗憾地意识到自己没有切割木头的锯子,于是用长木板将其镶嵌到Farmer Don’s Farm上,礼貌地询问他是否可以借用锯子。

壁橱资本家农夫唐(Farmer Don)不借给FJ锯,而是提议就木板中的N -1个切口向农夫约翰收费。切割一块木头的费用恰好等于其长度。切割一块长度为21的木板的成本为21美分。

然后,农夫唐让农夫约翰决定切割木板的顺序和位置。帮助农夫约翰确定他可以用来制作N块木板的最低金额。FJ知道他可以按各种不同的顺序切割木板,这将导致不同的费用,因为最终的中间木板长度不同。

输入项

第1行:一个整数N,木板数
第2行。N +1:每行包含一个整数,描述所需木板的长度
输出项

第1行:一个整数:要进行N -1次削减,他必须花费的最低金额
样本输入

3
8
5
8
样本输出

34
暗示

他想将一块长度为21的木板切成长度分别为8、5和8
的一块。原始木板的尺寸为8 + 5 + 8 = 21。第一次切割的成本为21,应用于将电路板切割成13和8的尺寸。第二次切割的成本为13,应用于将13切割为8和5的尺寸。这将成本21 + 13 = 34 。如果将21削减为16,将5削减,则第二次削减将花费16,总共37(超过34)。

这道题应该是一个哈夫曼树问题 直接上代码
1.

typedef long long ll;

//输入
int n,l[maxn];

void solve(){
	ll ans=0;
	
	//直到最大到木板为 1块为止 
	while(n>1){
		//求出最短的板mii1和次短的板mii2
		int mii1=0,mii2=0;
		if(l[mii1]>l[mii2]) swap(mii1,mii2);
		
		//这样可以求出最短和次短值***** 
		for(int i=2;i<n;i++){
			if(l[i]<l[mii1]){
				mii2=mii1;
				mii1=i;
			}
			else if(l[i]<l[mii2]){
				mii2=i;
			}
		} 
		
		//将这两块板合并
		int t=l[mii1] +l[mii2];
		ans+=t;
		
		//此处还不太懂 明天问问学长 
		if(mii1==n-1) swap(mii1,mii2);
		l[mii1]=t;
		l[mii2]=l[n-1];
		n--; 
	}
	printf("%lld\n",ans);
} 

上面的代码复杂度是O(n^2)
然后本题可以用O(NlogN)的时间求解

#include<bits/stdc++.h>
using namespace std;
typedef long long l1;

//输入
int n,l[maxn];

void solve(){
	ll ans=0;
	
	//声明一个从小到大取出数值的优先队列 
	priority_queue<int,vector<int>,greater<int>>que;
	for(int i=0;i<n;i++){
		que.push(l[i]);
	} 
	
	//直到最大到木板为 1块为止 
	while(que.size()>1){
		
		//求出最短的板和次短的板
		int l1,l2;
		l1=que.top();
		que.pop();
		l2=que.top();
		que.pop();
		
		
		//将这两块板合并
		ans+=l1+l2;
		que.push(t);
		
	}
	printf("%lld\n",ans);
} 

时间不够了 下次再早点开始写
就酱紫 88!

发布了16 篇原创文章 · 获赞 0 · 访问量 117

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/103413755