您的位置:首页 > Web前端

POJ 2718 Smallest Difference

2014-07-06 13:26 344 查看
链接:http://poj.org/problem?id=2718

题目:

Smallest Difference

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 3927Accepted: 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: