注:思路分析来源于ID为jasison的博主http://blog.csdn.net/jasison/article/details/8477279,代码也是模仿而写,稍有优化。(请支持正版原创)
题意:
给定n(2 <= n <= 10)个不重复的十进制数字('0'-'9'),让这n个数字不重复使用地构成两个数,使这两个数的差的绝对值最小。
比如,0 1 2 4 6 7,构成176 和 204 能使差最小为28。
思路:
贪心。分情况讨论。
1)是有奇数个数的话,那么,选择非零的最小的数字作为较大数的最高位,最后一位数字作为较小数的最高位,然后较大数从后往前取次位,较小数从前往后取次位。
如0 1 2 4 5 7 8,较大数的最高位就是1(次高位可以直接判断出来是0),较小数的次高位就是8,然后依次取,得到(10,8),(102,87),(1024,875),就能得到答案。
2)是有2个数的话,那么直接两个数相减就能得到答案。
3)非2个的偶数个数,这是比较麻烦的一种情况,首先必须使最高位的差最小,就可以遍历一遍找到最高位的差的最小值。然后再遍历一遍,对每一对最高位的差为最小值的两个数进行枚举,较小数的最高位为较小的那个数,较大数的最高位为较大的那个数,较大数的次位从前往后取,较小数的次位从后往前取。
如1 3 5 7,最高位的差为2,枚举所有的最高位的差为2 的数对(1,3),(3,5),(5,7)。然后取次位,分别得到(1,3)-> (17,35)= 18,(3,5)-> (37,51)= 14,(5,7)-> (53,71)= 18,比较得到答案为14。
#include <iostream>
#include<cstdio>
using namespace std;
struct Temp
{
int x;
int y;
};
int main()
{
int T;
cin>>T;
getchar();
while(T--)
{
int a[11],n=0,ans,num1,num2;
char c;
while(cin.get(c))
{
if(c=='\n')
break;
else if(c!=' ')
a[n++]=c-'0';
}
if(n==2) ans=a[1]-a[0];
else
{
if(n%2!=0)
{
num1= a[0]==0? a[1]*10:a[0]*10+a[1];
num2= a[n-1];
for(int i=0;i<(n-3)/2;++i)
{
num1=10*num1+a[i+2];
num2=10*num2+a[n-i-2];
}
ans = num1-num2;
}
else
{
int dif=11,count=0;
for(int i= a[0]==0? 1:0 ;i<n-1;i++)
{
if(a[i+1]-a[i]<dif)
dif=a[i+1]-a[i];
}
Temp temp[11];
for(int i= a[0]==0? 1:0 ;i<n-1;i++)
{
if(a[i+1]-a[i]==dif)
{
temp[count].x=a[i];
temp[count].y=a[i+1];
count++;
}
}
ans=1000000000;
for(int i=0;i<count;i++)
{
int h=1;
num2=temp[i].y;
for(int j=0;h<=n/2-1;j++)
{
if(a[j]!=temp[i].x&&a[j]!=temp[i].y)
{
num2=num2*10+a[j];
h++;
}
else
continue;
}
h=1;
num1=temp[i].x;
for(int j=n-1;h<=n/2-1;j--)
{
if(a[j]!=temp[i].x&&a[j]!=temp[i].y)
{
num1=num1*10+a[j];
h++;
}
else
continue;
}
if(ans>num2-num1)
ans=num2-num1;
}
}
}
cout<<ans<<endl;
}
return 0;
}