简单的字符串处理,枚举即可。
比对的条件是使用的字母的集合是给定集合的子集,且价值最大。
考虑到猥琐的输出顺序,我先枚举一次求出max,再枚举一次输出符合条件的串。
具体的顺序处理见我的程序。
第一次在usaco上爆内存。它的英文是resource limits exceeded.恩学会了。
程序中maxm显然不需要取40001 ,极端情况下maxm=7!+6!+5!+4!+3!+2!+1+(3!+2!+1)*(4!+3!+2!+1)=14102。
而实际数据中的m远远小于这个数。(linux 下的calculator好强大,粘贴上面那个算式,立刻出解)
code
/*
USER:zyn19961
TASK:lgame
LANG:C++
*/
#include<cstdio>
#include<cstring>
int const maxm=14102;
char t[8];
int q[maxm][127];
int qq[127];
char word[maxm][8];
int score[maxm];
int na[127]={2,5,4,4,1,6,5,5,1,7,6,3,5,2,3,5,7,2,1,2,4,6,6,7,5,7};
int nn[127];
int m=1;
int max=0;
int ans1[maxm];
int ansa[maxm];
int ansb[maxm];
int main(){
freopen("lgame.in","r",stdin);
freopen("lgame.out","w",stdout);
memset(qq,0,sizeof(qq));
memset(q,0,sizeof(q));
memset(score,0,sizeof(score));
for(int i=0;i<=25;i++)
nn['a'+i]=na[i];
scanf("%s",t);fclose(stdin);
for(int i=0;i<=strlen(t);i++)
qq[t[i]]++;
freopen("lgame.dict","r",stdin);
for(;;){
scanf("%s",word[m]);
if(word[m][0]=='.'){
m--;
break;
}
memset(q[m],0,sizeof(q[m]));
for(int i=0;i<=strlen(word[m]);i++)
q[m][word[m][i]]++;
bool flag=true;
for(int i='a';i<='z';i++)
if(q[m][i]>qq[i]){
flag=false;
break;
}
if(flag){
for(int i='a';i<='z';i++)
score[m]+=q[m][i]*nn[i];
m++;
}
}
for(int i=1;i<=m;i++){
bool flag=true;
for(int k='a';k<='z';k++)
if(q[i][k]>qq[k]){
flag=false;
break;
}
if(score[i]>max&&flag)
max=score[i];
for(int j=i+1;j<=m;j++){
bool flag=true;
for(int k='a';k<='z';k++)
if(q[i][k]+q[j][k]>qq[k]){
flag=false;
break;
}
if(score[i]+score[j]>max&&flag)
max=score[i]+score[j];
}
}
printf("%d\n",max);
for(int i=1;i<=m;i++){
bool flag=true;
for(int k='a';k<='z';k++)
if(q[i][k]>qq[k]){
flag=false;
break;
}
if(score[i]==max&&flag)
printf("%s\n",word[i]);
for(int j=i+1;j<=m;j++){
bool flag=true;
for(int k='a';k<='z';k++)
if(q[i][k]+q[j][k]>qq[k]){
flag=false;
break;
}
if(score[i]+score[j]==max&&flag)
printf("%s %s\n",word[i],word[j]);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}