poj3253 哈夫曼贪心

题意:把木板切成长度如第二行(及以后)的n块(第一行为n)木板,且切断木板耗费的能量为当前木板本身的长度,想办法求出 所需最少能量并输出。
注意:输出结果要用long long 来存,int存不下
思路:先找问题切入点,求出所需最少能量,那就考虑怎样才能在给定的切割方案中寻找最省力的方案。
从这题给的数据来看就要倒过来想问题,也就是说把一段段切好的木板不断合拢回原来长度的过程,每一步都耗费合拢的两块木板长度的力量,怎样才能让每一步耗费的力量最小化即可。
这样问题就清晰了,每一次都找最小的和次小的木板进行合并,直到合并为一个木板,这样每一步都耗费最少的力气,到最后也就是最优的结果,就像哈夫曼编码一个道理。
实现方法:实现方法很简单,用堆来存木板,每次取出两根最短的木板进行合并,再把合并后的木板放回堆中,并记下耗费的力量,直到堆里就剩下一个元素即可(此时木板就合并为一根了)。
java

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

import javax.management.Query;

public class Main {

    /**
     * @param args
     */
    static Scanner cin = new Scanner(System.in);
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        while(cin.hasNext()){       
            solve();    
        }
    }

    private static void solve() {
        // TODO Auto-generated method stub
        int n = cin.nextInt();      
        Queue< Integer> q  = new PriorityQueue<Integer>();
        for(int i = 0 ; i < n ; i++){
            int t = cin.nextInt();
            q.add(t);
        }
        long  ans = 0;
        while(q.size() != 1){
            int a = q.poll();
            int b = q.poll();
            ans += a+b;
            q.add(a+b);
        }
        System.out.println(ans);
    }
}

C++

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int n,a[20005],sum;
void solve()    //通过模拟解决 O(n^2)
{
    int l,r;
    long long ans = 0;
    while(n > 1)
    {
        l = 0,r = 1;
        if(a[l] > a[r])
            swap(l,r);
        for(int i = 2 ; i < n ; i++)
            if(a[i] < a[l])
            {
                r = l;
                l = i;
            }
            else if( a[i] < a[r] )
            {
                r = i;
            }
        int t = a[l] + a[r];
        ans += t;
        if(l == n-1)
            swap(l,r);
        a[l] = t;
        a[r] = a[n-1];
        n--;
    }
    printf("%lld\n",ans);
}
void solve_stl()    //STL优先级队列解决 n×lg(n)
{
    int l,r,t;
    long long ans = 0;
    priority_queue<int,vector<int>,greater<int> > q;
    for(int i = 0 ; i < n ; i++)
        q.push(a[i]);
    while(q.size() > 1)
    {

        l = q.top();
        q.pop();
        r = q.top();
        q.pop();
        t = l + r;
        ans += t;
        q.push(t);
    }
    printf("%lld\n",ans);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        sum = 0;
        for(int i = 0 ; i < n ; i++)
        {
            scanf("%d",&a[i]);
                sum += a[i];
        }
        //solve();
        solve_stl();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值