POJ 2718 Smallest Difference

链接:http://poj.org/problem?id=2718

题目:

Smallest Difference
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 3927 Accepted: 1098

Description

Given a number of distinct decimal digits, you can form one integer by choosing a non-empty subset of these digits and writing them in some order. The remaining digits can be written down in some order to form a second integer. Unless the resulting integer is 0, the integer may not start with the digit 0.

For example, if you are given the digits 0, 1, 2, 4, 6 and 7, you can write the pair of integers 10 and 2467. Of course, there are many ways to form such pairs of integers: 210 and 764, 204 and 176, etc. The absolute value of the difference between the integers in the last pair is 28, and it turns out that no other pair formed by the rules above can achieve a smaller difference.

Input

The first line of input contains the number of cases to follow. For each case, there is one line of input containing at least two but no more than 10 decimal digits. (The decimal digits are 0, 1, ..., 9.) No digit appears more than once in one line of the input. The digits will appear in incre asing order, separated by exactly one blank space.

Output

For each test case, write on a single line the smallest absolute difference of two integers that can be written from the given digits as described by the rules above.

Sample Input

1
0 1 2 4 6 7

Sample Output

28


题意:把一组数字(个数在2到10之间),分成两部分A和B,A中的数字可以按任意顺序放置,形成一个十进制数a,B中也是如此,求a和b差的绝对值的最小值。

解题思路:

先统计这组数的个数n,再将其对半分成两部分。A中有n/2个数字,B中有n - n/2个数字,只有这样分才能使a和b相差最小(当a和b相差最小时,a和b要么是有相同的位数,要么是相差一位)。我们可以用dfs来做,用dfs枚举出所有满足条件的a(a如果不是个位数,首位不可以是0),再计算出最优的b,要计算b的值得话,需要分成两种情况:1.当n为偶数时,B的元素的个数也是偶数个,根据a的首位h,①我们在剩余的没有使用过的数中找出比h小的最大值,作为b的首位,剩余元素从大到小排列,这样就得到比a小的与a最接近的数b了;②我们还要求出比h大的最小值,作为b的首位,剩余元素从小到大排列,这样就找到比a大的最接近a的数b了;2.当n为奇数时,B中的元素个数也是奇数,我们b一定比a大,剩余元素从小到大排列得到b(首位不可以是0)。PS:这里有一点要注意(WA点),当a不是个位数时,0不能放在首位,对于b也是如此。

几组易错的数据:

0 6
6
0 2 5
15
0 9 1 3
11


代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int MAXN = 21;

int ans, m, n, vis[MAXN], v[MAXN];

void dfs(int a[], int p)
{
    if(p == m)
    {
        int b[MAXN], c = 0, d = 0, e = 0, t = 0;
        for(int i = 0; i < m; i++)
        {
            e = 10 * e + a[i];
        }
        for(int i = 0; i < n; i++)
        {
            if(!vis[i]) b[t++] = v[i];
        }
        if(n == 2 * m)
        {
            int imin = 20, imax = -1;
            for(int i = 0; i < n - m; i++)
            {
                if(b[i] < a[0] && imax < b[i])
                {
                    imax = b[i];
                }
                if(b[i] > a[0] && imin > b[i])
                {
                    imin = b[i];
                }
            }
            if(-1 != imax) c = imax;
            if(20 != imin) d = imin;
            sort(b, b + n - m);
            if(0 == imax && n > 3) imax = b[1], c = b[1];
            for(int i = 0; i < n - m; i++)
            {
                if(b[n - m - 1 - i] != imax)
                    c = 10 * c + b[n - m - 1 - i];
                if(b[i] != imin)
                    d = 10 * d + b[i];
            }
            if(-1 != imax) ans = min(ans, abs(c - e));
            if(20 != imin) ans = min(ans, abs(d - e));
        }
        else
        {
            sort(b, b + n - m);
            int tmp = (0 == b[0] ? b[1] : b[0]);
            c = tmp;
            for(int i = 0; i < n - m; i++)
            {
                if(b[i] != tmp)
                {
                    c = 10 * c + b[i];
                }
            }
            ans = min(ans, abs(c - e));
        }
        return ;
    }
    for(int i = 0; i < n; i++)
    {
        if(!vis[i])
        {
            if(0 == p && 0 == v[i] && n > 3)
                continue;
            vis[i] = 1;
            a[p] = v[i];
            dfs(a, p + 1);
            vis[i] = 0;
        }
    }
}

int main()
{
    int t, a[MAXN];
    char s[MAXN];
    scanf("%d", &t);
    getchar();
    while(t--)
    {
        gets(s);
        n = 0;
        ans = 0x3fffffff;
        memset(vis, 0, sizeof(vis));
        memset(a, 0, sizeof(a));
        int len = strlen(s);
        for(int i = 0; i < len; i++)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                v[n++] = s[i] - '0';
            }
        }
        m = n / 2;
        dfs(a, 0);
        printf("%d\n", ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值