题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1800
题目大意:
给你一堆士兵的等级,等级高的的士兵可以当等级小的士兵的师傅,一个士兵最多一个师傅(可以没有),一个师傅最多1个徒弟(可以没有),如果是师徒关系,可以用一把扫帚练习技能,问你如果全部士兵都用过扫帚练习时最小需要的扫帚数量。
解题思路:
实质就是字典树的应用,但是要联想到字典树需要一定的基础。如果所有士兵等级都不同,则就可以用一条师徒链,所以就需要一把扫帚,而如果出现2个相同等级的士兵,则需要开辟另外一条师徒链,以此类推,发现只要求出等级相同的最多士兵数,就需要多少把扫帚。
注意地方:前导0的处理,1和01和001都是同一个数字(字符串处理,不是整型,所以必须处理前导0)。如果不处理,则需要1把扫帚,处理后才是3把扫帚。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define MAXN 50000
int num, maxn;
struct Dictree
{
int num;
Dictree *tire[30];
}*head;
Dictree Head[MAXN];
int fun(char str[]) //去掉前导的0
{
int i, len;
len = strlen(str);
for(i = 0; i < len; ++i)
if(str[i] != '0')
break;
return i;
}
void insert(int start, char str[]) //start为去掉前导0后的第一个位置
{
int len, temp;
head = &Head[0]; //字典树入口
len = strlen(str);
for(int i = start; i < len; ++i)
{
temp = str[i] - 48;
if(head->tire[temp] == NULL)
head->tire[temp] = &Head[++num];
head = head->tire[temp];
}
if(head->num != 0)
head->num++;
else
head->num = 1;
maxn = max(maxn, head->num); //需要的扫帚数
}
int main()
{
int ncase;
char str[32];
while(scanf("%d", &ncase) != EOF)
{
memset(Head, 0, sizeof(Head));
num = 0;
maxn = 0;
for(int i = 1; i <= ncase; ++i)
{
scanf("%s", str);
insert(fun(str), str);
}
printf("%d\n", maxn);
}
return 0;
}