就是给你一个数,排列组合,然后问如何排列之间的差值最小。
我之前的想法是一个递归,然后两个for循环枚举L1和L2,结果TLE了,然后想了一下剪枝发现没办法剪,然后看了一下别人的代码,用了next_permutation函数,虽然表示在书上看到过,但是具体确实没有用过,看到别人用了,虽然我也想用一下,但是还是觉得走正道吧,比较递归才是正道。不过这道题目,用了这个函数跑的比我的要快,6666
当然我也思考过我第一个为什么会T,原因就是我的排列是10个A的无序排列相乘,但是那种种还加了双重循环,所以T了。然后这里的话就是单纯的枚举一种,然后第二种就定了,所以只有排列组合的相乘。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath> using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = ;
int a[maxn];
bool vis[maxn];
int cnt;
int mini; void minidfs(int l2, int tmp, int val2, int val1){
if (l2 == ){
int t = abs(val2 - val1);
mini = min(mini, t);
return ;
}
for (int i = ; i <= cnt; i++){
if (vis[i]) continue;
if (val2 == && a[i] == && l2 != ) continue;
vis[i] = true;
minidfs(l2 - , tmp / , val2 + tmp * a[i], val1);
vis[i] = false;
}
} void dfs(int l1, int tmp, int val1){
if (l1 == ){
int t = ;
int l2 = (cnt + ) / ;
for (int i = ; i < l2; i++) t *= ;
//printf("%d\n", l2);
minidfs(l2, t, , val1);
return ;
}
for (int i = ; i <= cnt; i++){
if (a[i] == && val1 == && l1 != ) continue;
if (vis[i])continue;
vis[i] = true;
dfs(l1 - , tmp / , val1 + a[i] * tmp);
vis[i] = false;
}
} int main(){
int t; cin >> t;
getchar();
while (t--){
memset(vis, false, sizeof(vis));
memset(a, , sizeof(a));
cnt = ;
mini = inf;
char ch = '';
while (ch != '\n'){
scanf("%c", &ch);
if (ch >= '' && ch <= '') a[++cnt] = ch - '';
}
int tmp = ;
for (int i = ; i < cnt / ; i++) tmp *= ;
//printf("%d\n", tmp);
dfs(cnt / , tmp, );
printf("%d\n", mini);
}
return ;
}