vijos 中青局

先贴题目:

描述

中青局(中国青年OI局)要求你破译日本龟山自卫社的密码!
给你一个由大写字母和下划线组成的字符串,要你对其中不同字符进行编码(同样字符编码相同,一个字符编码可能有多位,如01,10,100等等),编码由0和1组成,这样一个字符串就会转化成01串,要求使其长度最小,且编码具有唯一性(不能由此编码得出多个不同的字符串),求编码的长度。

格式

输入格式

会有若干行字符串,以单独一行"END"为结束符.

输出格式

原字符串的长度乘8,编码长度和前者与后者的商,保留一位小数

样例1

样例输入1[复制]

AAAAABCD
THE_CAT_IN_THE_HAT
END

样例输出1[复制]

64 13 4.9
144 51 2.8


思路:

1、统计每个字符出现的频率

2、用贪心的方法,求出霍夫曼树的权值


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char n[27]=
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'};




bool complare(int a,int b) 
{   return a>b; }


int main()
{
char a[1000];
while(scanf("%s",a))
{
int len=strlen(a);
if(len==3&&a[0]=='E'&&a[1]=='N'&&a[2]=='D')break;
int num[27],i,k,s;//一共就27种字符
memset(num,0,27*sizeof(int));
for(i=0;i<len;i++)
{
k=0;
while(n[k++]!=a[i]);
num[k-1]++;
}
sort(num,num+27,complare);
s=0;
while(num[s++]!=0);
sort(num,num+s-1);

//注意可能输入的数据全部为一个类型,楼主在此处栽了2次
if(s==2)
{
printf("%d %d %.1lf\n",8*len,1*len,(8*len)/(1.0*len));
}
else
{
double result=0;

//利用贪心策略,解出树的权值
for(i=0;i<s-2;i++)
{
int temp;
temp=num[i]+num[i+1];
result+=temp;
for(k=i+2;k<s-1;k++)

//将算的的结果,再插入到有序队列中

if(temp>num[k])

num[k-1]=num[k];
else
break;
num[k-1]=temp;//保证数据能插入,即使是最后一个
}

printf("%d %.0lf %.1lf\n",8*len,result,(8*len)/result);
}
}
}

发布了16 篇原创文章 · 获赞 1 · 访问量 3823

猜你喜欢

转载自blog.csdn.net/GYJ_love/article/details/50511576