POJ-3253 Fence Repair

农夫约翰想修理牧场周围的一小段围栏。他测量围栏并认定他需要Ñ(1≤ Ñ ≤20000)厚木板,每一个都具有一些整数长度大号(1≤ 大号 ≤50000)单元。然后,他购买一块长板足够长,以便看到N块板(即,其长度是长度i的总和)。FJ忽略了“切口”,锯齿切割时锯屑的额外长度; 你也应该忽略它。

FJ悲伤地意识到,他没有一把砍伐木头的锯子,所以他用这张长板子将农民交给了Farmer Don's Farm,并礼貌地问他是否可以借用一把锯子。

一个衣柜资本家农夫唐(Donmer Don)并不是向FJ借一把锯子,而是向该农民约翰收取木板上N-1个切口的费用。砍一块木头的费用与其长度完全相等。切割长度为21的木板需要21美分。

农夫唐然后让农夫约翰决定顺序和地点切割木板。帮助Farmer John确定他可以用来创建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次)。

思路分析:

        这道题是我初试优先队列的题,所以一定要拿个小本子记下来。

        这道题的思路其实挺简单的,就是每次找两个最小的数求和,并将他们两数的和弹入队列即可,直到队列中只剩下最后一个元素即可。

此处主要代码为:

while(q.size()!=1)

        {

            ll a=q.top();

            q.pop();

            ll b=q.top();

            b=q.top();

            q.pop();

            ll c=a+b;

            ans+=c;

            q.push(c);

        }

文末最后提一下优先队列:

priority_queue ,greater >;这个是单增的队列

priority_queue ,less >;这个是单减的队列

AC代码:

#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int N;
ll l[20005];
ll ans;
priority_queue,greater >q;
int main()
{
    while(scanf("%d%*c",&N)!=EOF)
    {
        ans=0;
        while(!q.empty())
        {
            q.pop();
        }
        for(int i=0;i


你可能感兴趣的:(优先队列,贪心)