【POJ】3253围栏维修

【POJ】3253围栏维修

原题

Fence Repair

Time Limit: 2000MS
Memory Limit: 65536K

Description

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). FJ is ignoring the “kerf”, the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn’t own a saw with which to cut the wood, so he mosies over to Farmer Don’s Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn’t lend FJ a saw but instead offers to charge Farmer John for each of the N-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

Input

Line 1: One integer N, the number of planks
Lines 2…N+1: Each line contains a single integer describing the length of a needed plank

Output

Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts

Sample Input

3
8
5
8

Sample Output

34

Hint

He wants to cut a board of length 21 into pieces of lengths 8, 5, and 8.
The original board measures 8+5+8=21. The first cut will cost 21, and should be used to cut the board into pieces measuring 13 and 8. The second cut will cost 13, and should be used to cut the 13 into 8 and 5. This would cost 21+13=34. If the 21 was cut into 16 and 5 instead, the second cut would cost 16 for a total of 37 (which is more than 34).

翻译

围栏维修

时限: 2000MS
内存限制: 65536K

描述

农夫约翰想修复牧场周围的一小部分篱笆。他测量围栏,并发现他需要Ñ(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)。

思路

【SSL】1040 2004年分区联赛提高组之二 合并果子类似。
用堆。
先建堆。
堆排序
每次取出堆顶2个,求和,插入堆

代码

#include<iostream>
#include<cstdio>
using namespace std;
const long long maxlenth=20010;
class heap
{
    
    
	private:
		long long h[maxlenth],len=0;
		void up(long long x);//上移操作,把h[x]上移的合适位置
		void down(long long x);//下移操作,把h[x]下移的合适位置
		bool cmp(long long x,long long y); 
	public:
		void swap(long long &t1,long long &t2);//交换两数
		void build(long long x);//建堆  
		void sort();//堆排序
		void del(long long x);//删除操作,删除h[x]
		void push(long long x);//插入操作,把x加入堆的合适位置 
		long long top();//返回堆顶的值
		void pop();//删除堆顶 
		bool empty();//判断堆是否空 
		long long size();//返回堆的长度 
};
bool heap::cmp(long long x,long long y)//若x比y优,return 1,若y比x优,return 0 
{
    
    
	return h[x]<h[y];
}
void heap::swap(long long &t1,long long &t2)//交换两数 
{
    
    
	long long t=t1;
	t1=t2,t2=t;
	return;
}
void heap::up(long long x)//上移操作,把h[x]上移的合适位置 
{
    
    
	if(x>len)return;
	for(;x>1;x>>=1)
		if(cmp(x,x>>1)) swap(h[x],h[x>>1]);
		else return;
	return;
}
void heap::down(long long x)//下移操作,把h[x]下移的合适位置
{
    
    
	if(x<1)return;
	for(x<<=1;x<=len;x<<=1)
	{
    
    
		x+=(x+1<=len&&cmp(x+1,x));
		if(cmp(x,x>>1)) swap(h[x>>1],h[x]);
		else return;
	}
	return;
}
void heap::push(long long x)//插入操作,把x加入堆的合适位置 
{
    
    
	h[++len]=x;
	up(len);
	return;
}
void heap::del(long long x)//删除操作,删除h[x] 
{
    
    
	if(x<1||x>len)return;
	if(cmp(len,x)) h[x]=h[len--],up(x);
	else h[x]=h[len--],down(x);
	return;
}
void heap::sort()//堆排序 
{
    
    
	for(;len;h[1]=h[len--],down(1))
	{
    
    
		//a[i]=h[1];
		printf("%lld",h[1]);
	}
	return;
}
void heap::build(long long x)//建堆 
{
    
    
	long long i;
	for(len=0,i=1;i<=x;i++)
	{
    
    
	    //h[++len]=a[i];
		scanf("%lld",&h[++len]);
	    up(len);
	}
	return;
}
long long heap::top()//返回堆顶的值 
{
    
    
	if(empty())//堆为空 
		return 0;//崩溃 
	return h[1];
}
void heap::pop()//删除堆顶 
{
    
    
	del(1);
	return;
}
bool heap::empty()//判断堆是否空 
{
    
    
	return !len;
}
long long heap::size()//返回堆的长度 
{
    
    
	return len;
}
int main()
{
    
    
	heap h;
	long long n,ans=0,tem;
	scanf("%lld",&n);
	for(h.build(n);h.size()>1;h.push(tem))
	{
    
    
		tem=h.top();
		h.pop();
		tem+=h.top();
		h.pop();
		ans+=tem;
	}
	printf("%lld",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/115022630