HDU2527(哈夫曼树)

题目链接:

 

package D0727;
import java.util.Scanner;

public class HDu2527{

    class HFM {
        public int w, lChild, rChild, parent;

        public HFM(int w) {
            this.w = w;
            lChild = rChild = parent = -1;
        }
    }

    int len;
    HFM[] hfm;
    // //从huffman中找出两个最小的权值,并保存小标到m1和m2
    int m1, m2;

    public void selectMin() {
        int minw = Integer.MAX_VALUE;
        // 找最小的
        for (int i = 0; i < len; i++) {
            if (hfm[i].w < minw && hfm[i].parent == -1) {
                minw = hfm[i].w;
                m1 = i;
            }
        }
        // 找次小的
        minw = Integer.MAX_VALUE;
        for (int i = 0; i < len; i++) {
            if (hfm[i].w < minw && hfm[i].parent == -1 && i != m1) {
                minw = hfm[i].w;
                m2 = i;
            }
        }
    }

    // 构建哈夫曼树
    public void buildHFM(int[] w) {
        len = w.length;
        hfm = new HFM[2 * len - 1];
        for (int i = 0; i < len; i++)
            hfm[i] = new HFM(w[i]);
        for (int i = len; i < 2 * len - 1; i++)
            hfm[i] = new HFM(-1);

        while (len < hfm.length) {
            // 从huffman中选择两个权值最小的节点构建新节点
            selectMin();
            // 构造新节点
            hfm[len].w = hfm[m1].w + hfm[m2].w;
            hfm[len].lChild = m1;
            hfm[len].rChild = m2;
            // 修改m1和m2的父节点
            hfm[m1].parent = len;
            hfm[m2].parent = len++;
        }
    }

    // 求带权路径长
    public int WPL(int[] w) {
        int sum = 0;
        for (int i = 0; i < w.length; i++) {
            int ans = 0;
            int p = hfm[i].parent;
            while (p != -1) {
                ans++;
                p = hfm[p].parent;
            }
            sum += ans * w[i];
        }
        return sum;
    }

    public static void main(String[] args) {
        HDu2527 hdu = new HDu2527();
        Scanner sc = new Scanner(System.in);
        int n, m;
        String str;
        while (sc.hasNext()) {
            n = sc.nextInt();
            while (n-- > 0) {
                m = sc.nextInt();
                str = sc.next();

                // 处理字符串得到权值
                int len = 0;
                int[] w;
                int index = 0;
                for (int i = 0; i < str.length(); i++) {
                    boolean flag = true;
                    for (int j = i + 1; j < str.length(); j++) {
                        if (str.charAt(i) == str.charAt(j)) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag)
                        len++;
                }
                //考虑只有一种字母的情况
                if(len==1){
                    if(str.length()<=m)System.out.println("yes");
                    else System.out.println("no");
                    continue;
                }
                w = new int[len];
                char[] ch = str.toCharArray();
                for (int i = 0; i < ch.length; i++) {
                    if (ch[i] != ' ') {
                        int wi = 1;
                        for (int j = i + 1; j < ch.length; j++) {
                            if (ch[i] == ch[j]) {
                                wi++;
                                ch[j] = ' ';
                            }
                        }
                        w[index++] = wi;
                    }
                }
                /*for(int i = 0;i<w.length;i++){
                    System.out.println(w[i]);
                }*/
                hdu.buildHFM(w);
                int sum = hdu.WPL(w);
                //System.out.println(sum);
                if (sum <= m)
                    System.out.println("yes");
                else
                    System.out.println("no");
                //System.out.println();
            }
        }

    }

}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怎么演

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值