soj 1239. Smallest Differencev

来源:互联网 发布:ise14.7 端口 编辑:程序博客网 时间:2024/06/07 04:53

题意:

给定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";}}

原创粉丝点击