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);
        }
    }
  • 相关阅读:
    springboot项目创建父级依赖
    springboot整合测试
    springboot中使用RedisTemplate实现redis数据缓存
    springboot整合redis
    springboot整合shiro
    配置 maven 环境变量
    虚拟机和主机之间一系列工具包,开启双向复制粘贴后导致的内存占用问题
    mysql服务无法启动的问题
    Linux学习遇到的问题(权限问题:例如无法创建目录"**": 权限不够"等等)
    Windows 10 配置Git 环境变量(还有:安装git后,鼠标右键没有“git bush here”)
  • 原文地址:https://www.cnblogs.com/8023spz/p/9503181.html
Copyright © 2011-2022 走看看