POJ 3253 Fence repair

题目

在这里插入图片描述

分析

每次分割的开销等于自己的长度,其实也等于切割后的小板的长度,那么如果使每次切割的小班的长度组合起来最小,就可以实现每次切割长度最小

于是就把问题转化为——>每次求解最短板与第二短板组合
(类比哈夫曼树)

代码1

普通for循环实现,时间复杂度为n²

#include<iostream>
using namespace std;
typedef long long int ll;
#define N 99999999
int n ,L[N];

void sovle() {
	ll ans=0;//计算开销的 
	while(n>1) { //直到木板的数量为1
	
		//求出最短和第二短板
		int min1=0,min2=1;
		if(L[min1]>L[min2])//计算数组中第0块和第1块的大小
			swap(min1,min2);
		for(int i=2; i<n; i++) {
			if(L[i]<L[min1]) { //更新最小值 
				min2=min1;
				min1=i;
			} 
			else if(L[i]<L[min2]) {//更新第二小值 
				min2=i;
			}
		}
		
		int t=L[min1]+L[min2];//合并
		ans+=t; 
		
		if(min1==n-1)//如果min1==n-1,则需要交换才能保证其数值t在下一次搜索范围之内 
		swap(min1,min2);
		L[min1]=t;//将合并的值赋值给L[min1]
		L[min2]=L[n-1];//将下一轮搜索会忽略掉的数值L[n-1]赋值给第二短
		n--; 
	}
	cout<<ans<<endl;
}
int main() {
	cin>>n;
	for(int i=0; i<n; i++)
		cin>>L[i];//每块木板的长度
	sovle();
}

代码2

同样的思路,但是采用优先队列实现,算法的时间复杂度为nlongn

#include<iostream>
#include<queue> 
#define N 999999
typedef long long ll;
using namespace std;
int n,L[N];
void solve(){
	ll ans=0;
	
	//声明一个取值为从小到大的优先数列 
	priority_queue<int,vector<int>,greater<int>> Q;//priority_queue<int>默认top是最大值 
	for(int i=0;i<n;i++){
		Q.push(L[i]); 
	}
	
	//循环直到只有一块木板
	while(Q.size()>1){//计算队列中的个数 
		int l1,l2;
		l1=Q.top();Q.pop();//取出最小的 
		l2=Q.top() ;Q.pop() ;//取出第二小的 
		ans+=l1+l2;//相加 
		Q.push(l1+l2);  //加入队列 
	} 
	cout<<ans<<endl;
}
int main(){
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>a[i];
	solve();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MORE_77

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

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

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

打赏作者

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

抵扣说明:

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

余额充值