思路
这道题的题意刚开始理解错了,以为每一个字母的权重是所给字符串中的顺序(论英语的重要性)。
每个字母的权重还是字母表中的权重,
A
还是 1
相当于有五个空,把26个字母中的一部分逐个尝试填入。实际上就相当与5个for循环。
又因为多种可能时,需要输出字典序最大的,所以只要在搜索时优先选择权值大的字母即可。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int p[27][6], ans[6], aim;
bool vis[27], flag;
char op[10];
// 预处理,
void init()
{
for(int i=1; i<=26; i++)
{
int ans = 1;
for(int j=1; j<=5; j++)
p[i][j] = (ans*=i);
}
}
void dfs(int cur, int sum)
{
if(cur==6)
{
// 满足题意退出
if(sum==aim) flag = true;
return;
}
// 尝试填入字母,优先选取权重大的
for(int i=26; i>0; i--)
{
if(!vis[i])
{
ans[cur] = i;
vis[i] = true;
dfs(cur+1, sum+((cur&1)?1:-1)*p[i][cur]);
vis[i] = false;
}
if(flag) return;
}
}
int main()
{
init();
while(scanf("%d%s", &aim, op)&&strcmp("END", op))
{
// 将不能选取的字母直接设为已访问
memset(vis, true, sizeof(vis));
for(int i=0; i<strlen(op); i++)
vis[op[i]-'A'+1] = false;
flag = false;
dfs(1, 0);
if(flag)
for(int i=1; i<=5; i++) printf("%c", ans[i]+'A'-1);
else printf("no solution");
printf("\n");
}
return 0;
}