您的位置:首页 > 其它

vijos 中青局

2016-01-13 16:33 183 查看
先贴题目:


描述

中青局(中国青年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'
4000
,'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);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: