USACO 1.2 Name That Number

首先,程序是无文件版本的。所以用的是读入版。(USACO莫名的登陆不鸟了)


字母树保存名单,然后直接穷举情况,遍历字母树即可。

/*
ID:xueyifa4
PROG:namenum
LANG:C++
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

FILE *dict = fopen("dict.txt", "r");
FILE *in = fopen("namenum.in", "r");
FILE *out = fopen("namenum.out", "w");

char _name[12];
char _number[15];
bool flag(false);
int term[20][3] = { {0, 0, 0}, {0, 0, 0}, {0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10 ,11}, {12, 13, 14}, {15, 17, 18}, {19, 20, 21}, {22, 23, 24}};

class point
{
public:
	point *a[26];
	bool flag;
	point()
	{
		for (int i = 0; i != 26; ++ i)	a[i] = NULL;
		flag = false;
	}
}root;

void insert(point &t, char *s, int k, int length)//插入单词   root, 字符串, 第k个字符, 字符串长度
{
	if (k == length)
	{
		t.flag = true; //t这个节点为一个单词
		return;
	}
	int num = s[k] - 'A';
	if (t.a[num] == NULL) t.a[num] = new point;
	insert(*t.a[num], s, k + 1, length);
}

void dfs(int k, int number_length, char *number, char *name, point &T)//第k个位置填写的字母, 编号长度, 编号数组, 字母数组, 当前节点
{
	if (k == number_length)
	{
		if (!T.flag)	return;
		flag = true;
		for (int i = 0; i != k; ++ i)
			printf("%c", name[i]);
		printf("\n");
		return;
	}
	int num = number[k] - '0';
	if (num < 2)	return;
	for (int t = 0; t != 3; ++ t)//对应的是i这个单词
	{
		int i = term[num][t];
		if (T.a[i] == NULL)	continue;
		name[k] = i + 'A';
		dfs(k + 1, number_length, number, name, *T.a[i]);
	}
}

char tmp_s[100];
int main()
{
	for (int i = 1; i <= 24829; ++ i)
	{
		scanf("%s", tmp_s);
		insert(root, tmp_s, 0, strlen(tmp_s));
	}
	scanf("%s", _number);
	dfs(0, strlen(_number), _number, _name, root);
	if (!flag)	printf("NONE\n");
	return 0;
}

还有一个方法更简单,但是我是为了锻炼字母树- -

直接读入名字,判断这个名字对应的数字,因为字典就是字典序,所以直接判断一个输出一个即可。程序会非常短

你可能感兴趣的:(USACO 1.2 Name That Number)