链接:http://poj.org/problem?id=2718
题意:给定一堆数 , 分成两堆并内部任意组合成两个数。我们要求两个数的最小差值(不允许前导0)。
我是用dfs 暴搜 , 剪了一下枝(如果中间是第一个数小于第二个数(位数不足补零 && minn < 两数之差时剪枝)) , 我看别人用STL全排列只写了30多行 , dfs 的不过是五六十行 , 我这代码都不好意思贴上来了。。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
int num[10]; int arr[15] , minn;
void dfs(int step, int len);
int main()
{
int t,i,j;
char str[100];
scanf("%d",&t);
getchar();
while(t--)
{
gets(str);
int len = strlen(str) , number = 0;
memset(num,0,sizeof(num));
for(i=0; i<len; i++)
{
if(str[i]>='0' && str[i]<='9')
{
num[str[i]-'0']++;
++number;
}
}
minn = 999999999;
if(number == 10)
minn = 247;
else
dfs(0,number);
printf("%d\n",minn);
}
return 0;
}
void dfs(int step,int len)
{
if(step == len)
{
if(len == 2)
{
minn = arr[0]-arr[1];
if(minn < 0)
minn = -1*minn;
return ;
}
if(arr[len/2] == 0)
return ;
ll sum1 = 0 , sum2 = 0 ,i;
for(i=0; i<len/2; i++)
sum1 = sum1*10 + arr[i];
for(i=len/2; i<len; i++)
sum2 = sum2*10 + arr[i];
int ans;
if(sum1 > sum2)
ans = sum1 - sum2;
else
ans = sum2 - sum1;
minn = minn > ans ? ans : minn;
return ;
}
if(step >=1 && arr[0]== 0 || (step>len/2 && arr[len/2]==0))
return ;
if(step > len/2)
{
int i,sum1= 0, sum2= 0;
for(i=0; i<len/2; i++)
sum1 = sum1*10 + arr[i];
for(i=len/2; i<step; i++)
sum2 = sum2*10 + arr[i];
for(; i<len; i++)
sum2 *= 10;
// cout<<"hha ; "<<sum1<<" "<<sum2<<endl;
if(minn < abs(sum1 - sum2) && sum1 < sum2)
return ;
}
for(int i=0; i<=9; i++)
{
if(num[i] == 1)
{
num[i] = 0;
arr[step] = i;
dfs(step+1,len);
num[i] = 1;
}
}
}