这题居然一点都不卡我时间, 真是醉了啊~。。。。。。。。。。。。。。。
刚开始还在想26个字母里面选出5个进行排序的情况有7893600种, 可能会卡我时间, 逗得我还去想办法各种剪枝(还因为这个在dfs里面加了个sum>N的错误判断以至于我一直找不到为什么第一个样例就错了而其他样例都对了的原因)。这题就是考察一下细心程度吧。
思路:
要求:按字典序选择字母
规律:奇数都是加,偶数都是减
奇技淫巧:①用按位与(&)来判断奇偶性很炫酷,也略快;②用map来记录五个数分别对应哪一个字母
详细思路:读取数据, 从大到小排列字符串,dfs状态=(当前总和是sum, 当前要选择第cur个)
细心点:数据类型的选择(long long), 强制类型转换char->int, 以及pow的double->long long , 养成一个好的习惯。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn = 26+5;
int vis[maxn], N, len, flag;
char a[maxn];
map<int, char> M;
//void test1();
void Print() {
for(int i = 1; i <= 5; i++) printf("%c", M[i]);
printf("\n");
}
bool cmp(char i, char j) {
return i > j;
}
int convert(char ch) {
return (int)(ch-64);
}
bool dfs(LL sum, int cur) {
if(cur > 6 ) return false; //之前这个if里面还加了个 "|| sum > N ", 显然是不对的 ,所以不能这样剪枝
if(cur == 6 && sum == N) {
Print();
return true;
}
for(int i = 0; i < len; i++) {
if(!vis[i]) {
vis[i] = 1; M[cur] = a[i];
if((cur&1) && dfs(sum + (LL)pow(convert(a[i]), cur), cur+1)) return true;
else if(!(cur&1) && dfs(sum - (LL)pow(convert(a[i]), cur), cur+1)) return true;
vis[i] = 0; M[cur] = 0;
}
}
return false;
}
int main() {
while(scanf("%I64d%s", &N, a)!=EOF && (N || strcmp("END", a))) {
len = strlen(a);
sort(a, a+len, cmp);
//test1();
memset(vis, 0, sizeof(vis));
M.clear();
flag = 0;
flag = dfs(0, 1);
if(!flag) cout << "no solution" << endl;
}
return 0;
}
/*
void test1() {
cout << "N = " << N << endl;
cout << "a = " << a << endl;
cout << endl;
}
*/