7.9 单词游戏
源程序名 words.???(pas, c, cpp) 可执行文件名 words.exe 输入文件名 words.in 输出文件名 words.out |
【问题描述】
Io和Ao在玩一个单词游戏。
他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。
游戏可以从任何一个单词开始。
任何单词禁止说两遍,游戏中只能使用给定词典中含有的单词。
游戏的复杂度定义为游戏中所使用的单词长度总和。
编写程序,求出使用一本给定的词典来玩这个游戏所能达到的游戏最大可能复杂度。
【输入】
输入文件的第一行,表示一个自然数N(1≤N≤16),N表示一本字典中包含的单词数量以下的每一行包含字典中的一个单词,每一个单词是由字母A、E、I、O和U组成的一个字符串,每个单词的长度将小于等于100,所有的单词是不一样的。
【输出】
输出文件仅有一行,表示该游戏的最大可能复杂度。
【样例】
words.in words.out
5 16
IOO
IUUO
AI
OIOOI
AOOI
【问题分析】
枚举要取的单词,如果这个单词构成的图存在欧拉路(不一定是回路),则存在一个单词接龙的方案,这些单词的长度和就是一个解。答案是所有解的最大值。算法的时间复杂度是O(2n·n),n≤16。
PROGRAM words;
CONST
maxrijeci=100;
maxdulj=100;
VAR
n:integer;
nrijec:ARRAY[1..5, 1..5] OF integer;
dulj:ARRAY[1..5, 1..5, 1..maxrijeci] OF integer;
FUNCTION num(c:char):integer;
BEGIN
CASE c OF
'A':num:=1;
'E':num:=2;
'I':num:=3;
'O':num:=4;
'U':num:=5;
END;
END;
PROCEDURE citaj_ulaz;
VAR fin:text;
i, j, k, l, t:integer;
tmp:STRING[maxdulj];
prvi, zadnji:integer;
BEGIN
FOR i:=1 TO 5 DO
FOR j:=1 TO 5 DO
nrijec[i, j]:=0;
assign(fin, 'WORDS.in');
reset(fin);
readln(fin, n);
FOR i:=1 TO n DO
BEGIN
readln(fin, tmp);
prvi:=num(tmp[1]);
zadnji:=num(tmp[length(tmp)]);
inc(nrijec[prvi, zadnji]);
dulj[prvi, zadnji, nrijec[prvi, zadnji]]:=length(tmp);
END;
close(fin);
{ Sortiram rijeci po duljini }
FOR i:=1 TO 5 DO
FOR j:=1 TO 5 DO
FOR k:=1 TO nrijec[i, j]-1 DO
FOR l:=k+1 TO nrijec[i, j] DO
IF dulj[i, j, k]>dulj[i, j, l] THEN
BEGIN
t:=dulj[i, j, k];
dulj[i, j, k]:=dulj[i, j, l];
dulj[i, j, l]:=t;
END;
END;
FUNCTION nadji (zadnji:integer):integer;
VAR i:integer;
max:integer;
tmp:integer;
BEGIN
max:=0;
FOR i:=1 TO 5 DO
IF nrijec[zadnji, i]>0 THEN
BEGIN
dec(nrijec[zadnji, i]);
tmp:=dulj[zadnji, i, nrijec[zadnji, i]+1]+nadji(i);
inc(nrijec[zadnji, i]);
IF tmp>max THEN max:=tmp;
END;
nadji:=max;
END;
PROCEDURE rijesi;
VAR fout:text;
i:integer;
max, tmp:integer;
BEGIN
max:=0;
FOR i:=1 TO 5 DO
BEGIN
tmp:=nadji(i);
IF (tmp>max) THEN max:=tmp;
END;
assign(fout, 'WORDS.out');
rewrite(fout);
writeln(fout, max);
close(fout);
END;
{ Glavni program }
BEGIN
citaj_ulaz;
rijesi;
END.