题意:一组数分成两个数得到最小差~
思路:得到最小差的数是有规律的,两个数总是在数列中部(n/2)截取,使用DFS得到组合数,功能相当于next_permutation,但是更自由,可以求得前面的组合之后对后面再进行进一步的操作。
还有一个超时问题:一开始是得到一个数列的组合之后再从中间进行切割得到两数,但是超时了0.0.....后来采用的方法是将前面的数在 DFS中得到固定,在函数work中对后面(n-n/2)个数进行排列组合。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#define inf 0xfffffff
using namespace std;
string s;
int ans,k,sum,vis[11],num[11];
void dfs(int an)
{
int d[12]={0};
int m=0;
for(int i=0;i<k;i++)
if(vis[i]==0)
d[m++]=num[i];
do
{
int b=0;
for(int i=0;i<m;i++)
{
b=b*10+d[i];
}
if(m==1 || d[0]!=0)
ans=min(ans,max(an-b,b-an));
}while(next_permutation(d,d+m));
}
void DFS(int t)
{
if(t>=k/2)//>=
{
dfs(sum);
return ;
}
for(int i=0;i<k;++i)
{
if(vis[i])
continue;
if(sum==0&&num[i]==0)
continue;
vis[i]=1;
sum=sum*10+num[i];
DFS(t+1);
sum=(sum-num[i])/10;//回溯时用到
vis[i]=0;
}
return ;
}
int main()
{
int t;
cin>>t;
getchar();//如果用scanf()输入的话就不用getchar()了,,
while(t--)
{
//cin>>s;
getline(cin,s);
memset(vis,0,sizeof(vis));
k=0;
for(int i=0;i<s.length();++i)
if(s[i]>='0'&&s[i]<='9')
num[k++]=s[i]-'0';
int sum=0;
ans=inf;
DFS(0);
cout<<ans<<endl;
}
return 0;
}