信息解码(Message Decoding, ACM/ICPC World Finals 1991, UVa 213)

考虑下面的01串序列:
0, 00, 01, 10, 000, 001, 010, 011, 100, 101, 110, 0000, 0001, …, 1101, 1110, 00000, …
首先是长度为1的串,然后是长度为2的串,依此类推。如果看成二进制,相同长度的后
一个串等于前一个串加1。注意上述序列中不存在全为1的串。
你的任务是编写一个解码程序。首先输入一个编码头(例如AB#TANCnrtXc),则上述
序列的每个串依次对应编码头的每个字符。例如,0对应A,00对应B,01对应#,…,110对
应X,0000对应c。接下来是编码文本(可能由多行组成,你应当把它们拼成一个长长的01
串)。编码文本由多个小节组成,每个小节的前3个数字代表小节中每个编码的长度(用二
进制表示,例如010代表长度为2),然后是各个字符的编码,以全1结束(例如,编码长度
为2的小节以11结束)。编码文本以编码长度为000的小节结束。


这是遇到的第一个对我来说比较难的题,花了两三小时写出来的,而且有一点错误。getchar输入时,循环输入时回车键不易处理,添加一个判断语句控制忽略回车。因此加一个readchar函数。

最终代码是没问题的,感觉还可以再改进。
重点是readint函数,读取c个长度的二进制字符,返回出整型十进制数字。
redecodes读取给出的编码头

#include
#include
#include
#define MAXN 81
using namespace std;

char code[8][1<<8] = {0};//code[len][value] len是长度,value是对应十进制的值 

int readchar() {
	for(;;) 
	{
		int ch = getchar();
		if(ch != '\n' && ch != '\r') return ch; //一直读到非换行符为止
	}
} 
int readint(int c) //读取 c位二进制字符 
{
	int v = 0;
	
	while(c--) 
	{
		
		v = v + (1<<c) * (readchar() - '0');
	}
	return v; 
}
int readcodes() // 读取编码头 保存到code[][] 
{
	char head[MAXN];
	int i = 1, count = 0;
	scanf("%s", head);
	while(i <= strlen(head))
	{
		int j = 0;
		while(i <= strlen(head) && j < (1<<i)-1) // j< i的平方-1 
		{
			code[i][j++] = head[count++];
		}
		i++;
    }
    return 1;
}

 

int main()
{
	while(readcodes()) // 循环读取编码头 
	{
		printcodes();
		while(1)
		{
			int len = readint(3); // 读取前三位 转成二进制表示长度
			if(len == 0) break; 
			while(1)
			{
				int v = readint(len); // v代表每次读取len位的值 
				if(v == (1 << len)-1) break; // (1<
				putchar(code[len][v]); // 打印出 (len, v)的字母值 
			}
		}
		putchar('\n'); 
		memset(code, 0, sizeof(code));
	}
} 

你可能感兴趣的:(每天一道算法题,算法)