题目:
题目链接
给出0~9中几个数字,个数大于2,而且都不相同。让你把这几个数分成两组,组成两个数。如给出:1 3 4 5,这样就可以组成:13、45两个数..等等,求组成这两个数的最小差。如之前的13与45相差32,这组数最小的就是:41和35,差6.
解法:
1.解释:
不解释,爆搜。枚举所有组合,进行稍微剪枝就行了。剪枝策略:
- 这组数一定是对半分,个数最多相差1.
- 0不能开头
2.具体:
其中最主要的是
- 枚举方法:采用二进制枚举。
- 给出其中一组数后:求该组数的排列。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string.h>
#include <cmath>
using namespace std;
//求排列
void perm(int s[],int k, int r[], int &total, int size_s,int ans)
{
if(k == size_s-1){
ans = ans*10 + s[k];
r[total++] = ans;
return ;
}
for(int i = k; i<size_s; i++){
swap(s[i],s[k]);
if(!(k==0 && s[k]==0)) perm(s,k+1,r,total,size_s,ans*10+s[k]);
swap(s[i],s[k]);
}
return ;
}
int main()
{
int N,a[10+1];
string ch;
scanf("%d",&N);
getchar();
while(N--)
{
memset(a,sizeof(a),0);
getline(cin,ch);
int len = ch.length();
int dig = 0;
for(int i = 0; i<len; i++)
if(ch[i] != ' ') a[dig++] = ch[i] - '0';
int ans = 100000000;
int res1[120+5],res2[120+5];
for(int i = 1; i<(1<<dig); i++) //二进制枚举
{
int s1[10],k1 = 0;
int s2[10],k2 = 0;
for(int k = 0; k<dig; k++){
if(i & (1<<k))
s1[k1++] = a[k];
else s2[k2++] = a[k];
}
if(abs(k1-k2)>=2) continue;
int total1 = 0, total2 = 0;
perm(s1,0,res1,total1,k1,0);
perm(s2,0,res2,total2,k2,0);
for(int i = 0; i<total1; i++){
for(int j = 0; j<total2; j++)
ans = min(ans, abs(res1[i]-res2[j]));
}
}
printf("%d\n",ans);
}
return 0;
}