zoukankan      html  css  js  c++  java
  • poj 2718 Smallest Difference

    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
    

    Source

    next_permutation枚举全排列,从中间分开,各自组成一个数,进行更新最小差距。
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define MAX 0
    #define inf 0x3f3f3f3f
    using namespace std;
    int c,cc,s[10];
    int m;
    
    int main() {
        int t;
        char ch;
        scanf("%d
    ",&t);
        while(t --) {
            c = 0;
            m = 987654321;
            while((ch = getchar()) != '
    ') {
                if(isdigit(ch))s[c ++] = ch - '0';
            }
            int cc = (c % 2 ? c / 2 : c / 2 - 1);
            while (!s[0])next_permutation(s,s + c);
            do {
                int a = 0,b = 0;
                if(s[cc + 1]) {
                    for(int i = 0;i <= cc;i ++) {
                        a = a * 10 + s[i];
                    }
                    for(int i = cc + 1;i < c;i ++) {
                        b = b * 10 + s[i];
                    }
                    m = min(m,abs(a - b));
                }
            }
            while(next_permutation(s,s + c));
            if(c == 2)m = abs(s[1] - s[0]);
            printf("%d
    ",m);
        }
    }

    贪心,对于奇数的,显然组成两个数位数不同,那么位数多的哪个数最高位肯定选最小的(不是0),第二位选第二小的。。依次,位数少的那个数高位选最大的,相反,这样大数尽可能小,小数尽可能大,差距就最小了

    那么对于偶数,两个数位数相同,那么高位的差距应该最小,先确定相邻两个数的最小差距,然后把差距等于最小差距的情况都枚举一下,还是遵循小的数尽可能大,大的数尽可能小,这样来更新最小差距。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define MAX 0
    #define inf 0x3f3f3f3f
    using namespace std;
    int c,cc,s[10];
    int m;
    int main() {
        int t;
        char ch;
        scanf("%d
    ",&t);
        while(t --) {
            c = 0;
            while((ch = getchar()) != '
    ') {
                if(isdigit(ch))s[c ++] = ch - '0';
            }
            int a = 0,b = 0;
            if(c % 2) {
                if(!s[0])swap(s[0],s[1]);///0不能做首位
                for(int i = 0;i <= c / 2;i ++) {
                    a = a * 10 + s[i];
                }
                for(int i = c - 1;i > c / 2;i --) {
                    b = b * 10 + s[i];
                }
                m = abs(a - b);
            }
            else {
                if(c == 2) {///特殊对待
                    m = abs(s[0] - s[1]);
                }
                else {
                    int d = 10;
                    m = 1000000;
                    for(int i = 0;i < c - 1;i ++) {
                        if(s[i] && s[i + 1] - s[i] < d) {///找到相邻差最小值
                            d = s[i + 1] - s[i];
                        }
                    }
                    for(int i = 0;i < c - 1;i ++) {
                        if(s[i] && s[i + 1] - s[i] == d) {///s[i]不为 0 切相邻两数差距最小
                            int j = 0,num = 0;
                            a = s[i];///小的数
                            b = s[i + 1];///大的数
                            while(j < c  && num + 1 < c / 2) {///从头排着加小的数  使大的数尽可能小
                                if(j != i && j != i + 1) {
                                    b = b * 10 + s[j];
                                    num ++;
                                }
                                j ++;
                            }
                            num = 0;
                            j = c - 1;
                            while(j >= 0 && num + 1 < c / 2) {///使小的数尽可能大
                                if(j != i && j != i + 1) {
                                    a = a * 10 + s[j];
                                    num ++;
                                }
                                j --;
                            }
                            m = min(m,abs(a - b));
                        }
                    }
                }
            }
            printf("%d
    ",m);
        }
    }
  • 相关阅读:
    2028 ACM Lowest Common Multiple Plus
    2032 杨辉三角
    2011 ACM 0和1思想
    grid
    Change position in observation
    1490 ACM 数学
    1489 ACM 贪心
    2009 ACM 水题
    Book Lending Registration
    MR1和MR2(Yarn)工作原理流程
  • 原文地址:https://www.cnblogs.com/8023spz/p/9503181.html
Copyright © 2011-2022 走看看