POJ3253 Fence Repair (二叉堆 | 优先队列 | huffman树 )

本文出自:http://blog.csdn.net/svitter

题意:

给你几根木板,让你连接起来,每次连接花费为两根长度之和。连接所有的木板,最后最小的花费是多少。


输入输出分析:

略。


算法数据结构分析:

这个题目用贪心即可。即,每次的取两根最小的,花费最少,最后花费就最少。

本题目可以用二叉堆的最关键就在于二叉堆的定义:

大根堆:上面的比下面的大;

小根堆:上面的比下面的小;

通过一维数组最后一个添加或者删除,进行调整。


记于2014.08.01:

后来补充上优先队列的解法。

STL中的priority_queue就是使用的二叉堆实现的。

另外附上优先队列的使用方法:

struct cmp1
{  
    bool operator ()(int &a,int &b)
	{  
        return a>b;//最小值优先   
    }  
};  
struct cmp2
{  
    bool operator ()(int &a,int &b)
	{  
        return a<b;//最大值优先   
    }  
};  
struct node1
{  
    int u;  
    bool operator < (const node1 &a) const 
	{  
       return u>a.u;//最小值优先   
    }  
};  
struct node2
{  
	int u;  
	bool operator < (const node2 &a) const 
	{  
        return u<a.u;//最大值优先   
	}  
}; 

priority_queue<int>q1;//采用默认优先级构造队列     
priority_queue<int,vector<int>,cmp1>q2;//最小值优先   
priority_queue<int,vector<int>,cmp2>q3;//最大值优先   
priority_queue<int,vector<int>,greater<int> >q4;//注意“>>”会被认为错误,   
                                                //这是右移运算符,所以这里用空格号隔开,最小值优先 
priority_queue<int,vector<int>,less<int> >q5;//最大值优先    
priority_queue<node1>q6;  //自定义优先级
priority_queue<node2>q7;



1.一般堆解法:

时间消耗:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

__int64 a[20010];
int m, n;

void heap(int m)
{
    int t;
    while(m * 2 <= n)//有子堆
    {
        m = m * 2;
        if(m < n && a[m] > a[m+1]) // 较大的子堆
        {
            m++;
        }
        if(a[m] < a[m / 2]) //
        {
            t = a[m];
            a[m] = a[m/2];
            a[m/2] = t;
        }
        else
            break;
    }
}

void push_heap()
{
    int i = n;
    __int64 x = a[n];
    while(i > 1 && a[i/2] > x)
    {
        a[i] = a[i/2];
        i /= 2;
    }
    a[i] = x;
}

void pop_heap()
{
    __int64 x;
    //swap top.root
    x = a[1];
    a[1] = a[n];
    a[n] = x;

    n--;
    heap(1);
}

void make_heap()
{
    int i;
    for(i = n / 2; i > 0; i --)//从n/2构建即可
    {
        heap(i);
    }
}

void ace()
{
    int i;
    __int64 cur0, cur1, cur, sum;
    while(~scanf("%d", &n))
    {
        for(i = 1; i <= n; i++)
        {
            scanf("%I64d", &a[i]);
        }
        make_heap();
        sum = 0;
        while(n != 1)
        {
            pop_heap();
            cur0 = a[n+1];
            pop_heap();
            cur1 = a[n+1];
            cur = cur0 + cur1;
            sum += cur;
            a[++n] = cur;
            push_heap();
        }
        printf("%I64d\n", sum);
    }
}

int main()
{
    ace();
    return 0;
}


2.类似冒泡解法

时间消耗:


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

__int64 a[20010];
int m, n;


void ace()
{
    int i;
    __int64 cur0, cur1, cur, sum;
    while(~scanf("%d", &n))
    {
        for(i = 1; i <= n; i++)
        {
            scanf("%I64d", &a[i]);
        }
        make_heap();
        sum = 0;
        while(n != 1)
        {
            pop_heap();
            cur0 = a[n+1];
            pop_heap();
            cur1 = a[n+1];
            cur = cur0 + cur1;
            sum += cur;
            a[++n] = cur;
            push_heap();
        }
        printf("%I64d\n", sum);
    }
}

int main()
{
    ace();
    return 0;
}



3.模板STL解法

#include <iostream>
#include <cstdio>
#include <queue>

#define lln long long 
using namespace std;

struct item 
{
    lln w;
    bool operator < (const item &a)const
    {
        return w > a.w;
    }
};

int n;
int main()
{
    item t;
    item t1, t2;
    int i;
    lln cost;
    priority_queue <item> Queue;
    while(~scanf("%d", &n))
    {
        for(i = 0; i < n; i++)
        {
            scanf("%lld", &t.w);   
            Queue.push(t);
        }    

        cost = 0;
        while(!Queue.empty())
        {
            t1 = Queue.top();
            Queue.pop();
            if(Queue.empty())
                break;
            t2 = Queue.top();
            Queue.pop();
            
            t1.w += t2.w;
            cost += t1.w;
            if(Queue.empty())
                break;
            Queue.push(t1);
        }
        printf("%lld\n", cost);
    }
    return 0;
}



转载于:https://my.oschina.net/u/1017188/blog/333823

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值