您的位置:首页 > Web前端

soj 1239. Smallest Differencev

2013-01-07 15:32 253 查看
题意:

给定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。

注意:

读入数据的时候可以用stringstream或其他。

代码:

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;
int t, n, num[10], a, b, ans;
string data;
int main()
{
ios::sync_with_stdio(false);
cin >> t;
getline(cin, data);
while (t --)
{
getline(cin, data);
n = 0;
stringstream sin(data);
while (sin >> num[n++]);
n --;
sort(num, num+n);
if (n == 2) ans =  num[1]-num[0];
else
{
if (n & 1)
{
a = num[0]==0 ? num[1]*10 : num[0]*10+num[1];
b = num[n-1];
for (int i = 0; i < (n-3)/2; ++ i)
{
a = 10*a + num[i+2];
b = 10*b + num[n-i-2];
}
ans = a-b;
}
else
{
int mp = num[0]==0 ? 1 : 0;
int md = num[mp+1] - num[mp];
for (int i = mp+1; i < n-1; ++ i)
{
if (num[i+1]-num[i] < md)
md = num[i+1]-num[i];
}
bool vis[10];
ans = 1000000000;
for (int i = mp; i < n-1; ++ i)
{
if (num[i+1]-num[i] == md)
{
memset(vis, false, sizeof(vis));
vis[i] = vis[i+1] = true;
a = num[i+1]; b = num[i];
for (int l=0,h=n-1; h>l; )
{
while (l<n && vis[l]) l ++;
while (h>0 && vis[h]) h --;
if (l < h)
{
vis[l] = vis[h] = true;
a = 10*a + num[l];
b = 10*b + num[h];
}
}
if (ans > a-b) ans = a-b;
}
}
}
}
cout << ans << "\n";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: