描述
在家里用电视机做字母游戏是很流行的,其中一种玩法是:每一个字母有一个数值与之对应.你收集字母组成一个或多个词以得到尽可能高的得分.除非你已有了 “找词的方法”(“a way with words”),你会把你知道的字都试一遍.有时你也许会查阅其拼写,然后计算得分。显然可以用计算机更为准确地完成此任务。上图示出了英文字母及其所对应的值,当给出英文单词(word) 的表列及收集的字母时,请找出所能形成的得分最高的词或词对(pairs of words)。
[编辑]格式
PROGRAM NAME: lgame
INPUT FORMAT:
(file lgame.in)
输入文件lgame.in中有一行由小写字母(`a'到`z')组成的字符串, 这就是收集到字母(就是可以使用的字母),字符串由至少3个字母至多7个字母(以任意顺序) 组成。
(file lgame.dict)
词典文件lgame.dict由至多40,000行组成,文件的最后一行有'.' 表示文件的结束。其它各行每一行都是由至少3个小写字母,至多7 个小写字母组成的字符串。文件中的词已按字典顺序排序。
OUTPUT FORMAT:
(file lgame.out)
在文件lgame.out的第一行,你的程序应写上最高得分(子任务A).使用上面图形中给出的字母-值对应表。
随后的每一行是由文件lgame.dict中查到的具有这个得分的所有的词和或词对(word pairs)(子任务B)。要利用图中给定的字母的值。
当两个词能够形成 一个组合(具有给定的字母)时,这两个词应该打印到同一行,两个词中间用一个空格隔开。不许重复表示词对,例如'rag prom'和'prom rag'是同样的词对,只输出字典顺序较小的那个。
输出要按照字典顺序排序,如果两个词对第一个单词的顺序相同,则按照第二个单词。一个词对中的两个单词可以相同。
[编辑]SAMPLE INPUT(file lgame.in)
prmgroa
[编辑]SAMPLE INPUT(file lgame.dict)
profile program prom rag ram rom .
[编辑]SAMPLE OUTPUT
24 program prom rag
很容易就能想到枚举,而且数据量很小,复杂度够了
主要是各种字符串匹配比较麻烦,幸亏有STL库,要不然估计很难写出来
/*
ID: your_id_here
PROG: lgame
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <fstream>
using namespace std;
int sco[255],cnt[255]={0},tmp[255],maxv=0,len,ch[9];
int num[9],all=0;
bool vis[9];
string ori;
map<string,int> mp;
map<string,bool> used;
vector<string> ans;
void dfs(string pre,string s,bool isSec) {
if(s.size()>=3) {
if(mp[s]!=0) {
if(s.size()==3&&!isSec&&len>=6)//因为最多只有7个字符,所以若存在两个字符串,则有一个必定为3个字符
dfs(s,"",true);
if(isSec) {
if(maxv<=mp[pre]+mp[s]) {
if(maxv<mp[pre]+mp[s]) {//如果发现值更大的单词组
maxv=mp[pre]+mp[s];
ans.clear();
used.clear();
}
if(pre<=s) {
if(!used[pre+" "+s]) {//只放入为放入过的
used[pre+" "+s]=true;
ans.push_back(pre+" "+s);
}
}
else {
if(!used[s+" "+pre]) {
used[s+" "+pre]=true;
ans.push_back(s+" "+pre);
}
}
}
}
else {
if(maxv<=mp[s]) {
if(maxv<mp[s]) {
maxv=mp[s];
ans.clear();
used.clear();
}
if(!used[s]) {
used[s]=true;
ans.push_back(s);
}
}
}
}
}
for(int i=0;i<all;++i) {
if(num[i]>0) {
--num[i];
string tmp=s;
tmp.push_back(ch[i]);
dfs(pre,tmp,isSec);
++num[i];
}
}
}
int main() {
ifstream fin("lgame.in");
ifstream dict("lgame.dict");
ofstream fout("lgame.out");
sco['q']=sco['j']=sco['z']=sco['x']=7;
sco['w']=sco['f']=sco['k']=sco['v']=6;
sco['y']=sco['p']=sco['g']=sco['h']=sco['b']=sco['m']=5;
sco['u']=sco['d']=sco['c']=4;
sco['o']=sco['l']=3;
sco['r']=sco['t']=sco['a']=sco['n']=2;
sco['e']=sco['i']=sco['s']=1;
string s;
fin>>ori;
len=ori.size();
for(int i=0;i<len;++i)//统计各单词出现
++cnt[ori[i]];
for(int i='a';i<='z';++i)
if(cnt[i]) {//将字符分组,可以避免同一个单词多次出现,相当于剪枝
ch[all]=i;
num[all++]=cnt[i];
}
while(dict>>s&&s[0]!='.') {
memset(tmp,0,sizeof(tmp));
for(int i=0;i<s.size();++i)
++tmp[s[i]];
int tot=0;
for(int i='a';i<='z';++i)
if(tmp[i]>cnt[i]) {//若字典中的单词i字符个数 大于 ori中i字符个数,则该单词无效
tot=-1;
break;
}
else
tot+=tmp[i]*sco[i];
if(tot!=-1)//若ori串能形成当前串,则记录其分值
mp[s]=tot;
}
dfs("","",false);
fout<<maxv<<"\n";
sort(ans.begin(),ans.end());//要按升序输出
for(int i=0;i<ans.size();++i)
fout<<ans[i]<<"\n";
return 0;
}