POJ 3253 Fence Repair(哈夫曼树)

poj 3253

题目大意

你希望得到n个长分别为 a1,a2,a3......an 的木板,给你一个长木板长为 a1+a2+a3......+an 你可以通过切n-1刀得到你想要的n个木板,但每切一刀有个代价,需要花费和所切木板长度数量相同的金钱,问最少需要花费多少金钱?

分析

不管怎么分最后都要分成n分,而每次分都是把一个节点分成两个,所以可以看出这是一个二叉树问题,叶节点就是 a1,a2,a3......an 。仔细观察后发现,由某个叶节点所引起的花费是: 叶节点权值(长度)*该节点深度(到达该节点所经过的切割数)。求所有节点带权路径长度和最小问题,也就是哈夫曼树。
对于这道题,最后把除了根节点以外的所有节点的权值加起来就是答案了,这等价于 sum(叶节点权值*叶节点深度)。
胡乱写的一个哈夫曼,结构体里的deep没用到。第一发wa改成long long int后过了。

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const int INF=999999999;
int n;
int a[20005];
struct HTnode
{
      int pa;
      int lchild,rchild;
      long long int w;
      int deep;
      int pos;
      friend bool operator<(HTnode a,HTnode b)
      {
          return a.w>b.w;
      }

}HT[50000];
int nodecount=0;
priority_queue<HTnode> Q;
void Init_Huffman_Tree()
{
      for(int i=1;i<=n;i++)
      {
           struct HTnode *ptr=&HT[++nodecount];
           ptr->deep=0;
           ptr->lchild=0;
           ptr->pa=0;
           ptr->rchild=0;
           ptr->w=a[i];
           ptr->pos=nodecount;
           Q.push(*ptr);
      }
}
void Huffman_Tree()
{
    while(1)
    {
        HTnode node1;
        HTnode node2;
        node1=Q.top();Q.pop();
        if(Q.empty())break;
        node2=Q.top();Q.pop();
        int pos1=node1.pos;
        int pos2=node2.pos;
        HT[pos1].pa=nodecount;
        HT[pos2].pa=nodecount;
        HT[++nodecount].lchild=pos1;
        HT[nodecount].rchild=pos2;
        HT[nodecount].pos=nodecount;
        HT[nodecount].pa=0;
        HT[nodecount].w=HT[pos1].w+HT[pos2].w;
        Q.push(HT[nodecount]);
    }
 }
 /*
 void Bianli(int pos)
 {
       int pos1=HT[pos].lchild;
       if(pos1!=0)
       {
             HT[pos1].deep=HT[pos].deep+1;
             Bianli(pos1);
       }
       int pos2=HT[pos].rchild;
       if(pos2!=0)
       {
             HT[pos2].deep=HT[pos].deep+1;
             Bianli(pos2);
       }
 }*/
int main()
{
   while(scanf("%d",&n)!=EOF)
   {
         nodecount=0;
         for(int i=1;i<=n;i++)
         {
               scanf("%d",&a[i]);
         }
        Init_Huffman_Tree();
        Huffman_Tree();
        /*
        for(int i=1;i<=nodecount;i++)
        {
              if(HT[i].pa==0){HT[i].deep=0;Bianli(i);}
              break;
        }*/
        long long int ans=0;
        for(int i=1;i<=nodecount;i++)
        {
              if(HT[i].pa!=0){ans+=HT[i].w;}
        }
        cout<<ans<<endl;
   }
}
/*
3
8
5
8
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值