Sicily 1239. Smallest Differencev

1239. Smallest Differencev

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

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 increasing 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
我的方法比较复杂,后来在网上看了贪心做的简直大神之作,先说说我的渣渣之作吧;
我的方法是:
1、两个数字直接输出啦;
2、假如是双数个,那么先找出两个数的第一位,两个数的第一位肯定要尽量靠近(注意第一位不能为零,下同),下面的代码中,我在find_min中先找到可以达到的差距最小值,然后选出这些值的组合,比如差距最小是1,那么组合是1和2,6和7(拿题目例子说明),然后用构造排列的方法构造两个数的后面的几位,并更新最小值;
3、如果是奇数个,方法和2中大同小异,只不过两个数的开头应该是差距最大的数,比如1,2,4,6,7,那么开头就是1和7,这样两个数才会尽量靠近,两个数的后面几位与2中类似构造;

效率较低,0.02s:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define INF 999999

bool num_to_used[10];//可以用的数字
int used_num;//可以用的数字的多少
int minn[10][2];//开头的最小差值组合
int min_num;//开头的最小差值组合的树目

void find_min() {
    int miinn = INF;
    min_num = 0;
    for (int i = 0; i < 10; i++) {//找到可以达到的开头最小差值
        for (int j = i + 1; j < 10; j++) {
            if (num_to_used[i] && num_to_used[j] && j - i < miinn && i != 0) {
                miinn = j - i;
            }
        }
    }
    for (int i = 0; i < 10; i++) {//构造开头最小差值组合
        for (int j = i + 1; j < 10; j++) {
            if (num_to_used[i] && num_to_used[j] && (j - i == miinn) && i != 0) {
                minn[min_num][0] = i;
                minn[min_num][1] = j;
                min_num++;
            }
        }
    }
}
    
int do_two() {
    find_min();
    int min_dif = INF;
    int j;
    int temp1[10], temp2[10];
    int permutation[11];
    int tem1, tem2;
    for (int i = 0; i < used_num - 2; i++) {//排列数组
        permutation[i] = i;
    }
    for (int i = 0; i < min_num; i++) {
        temp1[0] = minn[i][0];//两个数字的开头
        temp2[0] = minn[i][1];
        int rest[11];//剩下可以用的数字
        int k = 0;
        for (j = 0; j < 10; j++) {//找到剩下可以用的数字
            if (j != temp1[0] && j != temp2[0] && num_to_used[j]) {
                rest[k++] = j;
            }
        }
        int rest_num = k;
        //下面就是构造这两个数字了
        for (j = 0, tem1 = temp1[0], k = 1; j < rest_num / 2; j++, k++) {
            temp1[k] = rest[permutation[j]];
            tem1 = tem1 * 10 + temp1[k];
        }
        for (j = rest_num / 2, k = 1, tem2 = temp2[0]; j < rest_num; j++, k++) {
            temp2[k] = rest[permutation[j]];
            tem2 = tem2 * 10 + temp2[k];
        }
        if ((int)fabs(tem1 - tem2) < min_dif) {
            min_dif = (int)fabs(tem1 - tem2);
        }
        
        while (next_permutation(permutation, permutation + rest_num)) {//变换排列并构造数字,更新差值
            for (j = 0, tem1 = temp1[0], k = 1; j < rest_num / 2; j++, k++) {
                temp1[k] = rest[permutation[j]];
                tem1 = tem1 * 10 + temp1[k];
            }
            for (j = rest_num / 2, k = 1, tem2 = temp2[0]; j < rest_num; j++, k++) {
                temp2[k] = rest[permutation[j]];
                tem2 = tem2 * 10 + temp2[k];
            }
            if ((int)fabs(tem1 - tem2) < min_dif) {
                min_dif = (int)fabs(tem1 - tem2);
            }
        }
    }
    return min_dif;
}

int do_one() {
    int min_dif = INF;
    int min_head, max_head;
    int i, j, k = 0;
    for (int i = 1; i < 10; i++) {
        if (num_to_used[i]) {
            min_head = i;
            break;
        }
    }
    for (int i = 9; i > 0; i--) {
        if (num_to_used[i]) {
            max_head = i;
            break;
        }
    }
    int permutation[11];
    for (i = 0; i < used_num - 2; i++) {
        permutation[i] = i;
    }
    int rest[10];
    int temp1[10], temp2[10];
    temp1[0] = min_head;
    temp2[0] = max_head;
    int tem1;
    int tem2;
    for (j = 0; j < 10; j++) {
        if (j != temp1[0] && j != temp2[0] && num_to_used[j]) {
            rest[k++] = j;
        }
    }
    int rest_num = k;
    for (j = 0, k = 1, tem1 = temp1[0]; j < rest_num / 2 + 1; j++, k++) {
        temp1[k] = rest[permutation[j]];
        tem1 = tem1 * 10 + temp1[k];
    }
    for (j = rest_num / 2 + 1, k = 1, tem2 = temp2[0]; j < rest_num; j++, k++) {
        temp2[k] = rest[permutation[j]];
        tem2 = tem2 * 10 + temp2[k];
    }
    if ((int)fabs(tem1 - tem2) < min_dif) {
        min_dif = (int)fabs(tem1 - tem2);
    }
    while (next_permutation(permutation, permutation + rest_num)) {
        for (j = 0, k = 1, tem1 = temp1[0]; j < rest_num / 2 + 1; j++, k++) {
            temp1[k] = rest[permutation[j]];
            tem1 = tem1 * 10 + temp1[k];
        }
        for (j = rest_num / 2 + 1, k = 1, tem2 = temp2[0]; j < rest_num; j++, k++) {
            temp2[k] = rest[permutation[j]];
            tem2 = tem2 * 10 + temp2[k];
        }
        if ((int)fabs(tem1 - tem2) < min_dif) {
            min_dif = (int)fabs(tem1 - tem2);
        }
    }
    return min_dif;
}

int main() {
    int case_num;
    scanf("%d\n", &case_num);
    while (case_num--) {
        char temp[25];
        memset(num_to_used, false, sizeof(num_to_used));
        gets(temp);
        used_num = 0;
        for (int i = 0; temp[i] != '\0'; i++) {
            if (temp[i] != ' ') {
                num_to_used[temp[i] - '0'] = true;
                used_num++;
            }
        }
        if (used_num == 2) {//只有两个直接输出即可
            printf("%d\n", (int)fabs(temp[0] - temp[2]));
            continue;
        }
        if (used_num % 2 == 0) {//单双数分别处理
            printf("%d\n", do_two());
        } else {
            printf("%d\n", do_one());
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值