本题题意是把所给数分为两个非空集合,分别用这两个集合组成两个数,求组成数的最小绝对值。显然这是一条穷竭搜索的题目,不大于10个数暴力搜索似乎可以解决。既然要绝对值最小,那么两数的位数的绝对值也一定是最小的。所以自然会想到将数据分为奇数个和偶数个两种情况讨论。利用贪心的思想,当数据为奇数个时,取最小非零数为较大数的第一个数字。然后将剩下的偶数个数分为两组,将最小组合添加到较大数后面,最大组合作为较小数。当数据为偶数个时,利用贪心的思想,较大数和较小数的首位数字应该绝对值最小,所以应该挑选出绝对值最小的两个数,作为两数的首位数字。然后将剩下的偶数个数分为两组,将最小组合添加到较大数后面,最大组合添加到较小数后面。如果数据中绝对值最小的情况不止一种,那么还应该枚举出来,找最小者。原题链接
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int sum1,sum2,result;
int state[10],used[10];
void update(int k){
for(int j=0;j<(k-1)/2;j++) ///填充大数
for(int i=9;i>=0;i--) if(state[i]&&!used[i]){
sum1=sum1*10+i;
used[i]=1;
break;
}
for(int j=0;j<(k-1)/2;j++) ///填充小数
for(int i=0;i<10;i++) if(state[i]&&!used[i]){
sum2=sum2*10+i;
used[i]=1;
break;
}
result=min(result,sum2-sum1);
}
int main()
{
int n;
cin>>n;
while(n--){
char c,s;
int k=0;
result=0x7f7f7f7f;
memset(state,0,sizeof(state));
memset(used,0,sizeof(used));
while(cin>>skipws>>c>>noskipws>>s){
state[c-'0']=1;
k++;
if(s=='\n') break;
}
if(k&1){ ///如果输入的个数是奇数
for(int i=1;i<10;i++) if(state[i]){
sum1=0;sum2=i;
used[i]=1;
break;
}
update(k);
}
else{
int mm=9,tmp=-10;
for(int i=1;i<10;i++) if(state[i]) {mm=min(mm,i-tmp);tmp=i;}
for(int i=1;i<10-mm;i++) if(state[i]&&state[i+mm]) {
sum1=i;sum2=i+mm;
used[i]=used[i+mm]=1;
update(k);
memset(used,0,sizeof(used));
}
if(mm==9) result=tmp; ///只有两个数且其中一个数为0
}
cout<<result<<endl;
}
return 0;
}