zoukankan      html  css  js  c++  java
  • PAT 甲级 1038 Recover the Smallest Number (30 分)(思维题,贪心)

    1038 Recover the Smallest Number (30 分)
     

    Given a collection of number segments, you are supposed to recover the smallest number from them. For example, given { 32, 321, 3214, 0229, 87 }, we can recover many numbers such like 32-321-3214-0229-87 or 0229-32-87-321-3214 with respect to different orders of combinations of these segments, and the smallest number is 0229-321-3214-32-87.

    Input Specification:

    Each input file contains one test case. Each case gives a positive integer N (≤) followed by N number segments. Each segment contains a non-negative integer of no more than 8 digits. All the numbers in a line are separated by a space.

    Output Specification:

    For each test case, print the smallest number in one line. Notice that the first digit must not be zero.

    Sample Input:

    5 32 321 3214 0229 87
    

    Sample Output:

    22932132143287

    题意:

    给一些字符串,求它们拼接起来构成最小数字的方式

    题解:

    必须保证两个字符串构成的数字是最小的才行,所以cmp函数写成return a + b < b + a;的形式,保证它排列按照能够组成的最小数字的形式排列。没有想到,但是我意识到了直接比较a<b是不行的,还自己写了这个,发现值只得了26分,最后想不出来看题解,有一种原来如此的感觉。1035,1036,1037,1038这一套都较为简单,就是要注意细节。

    /*bool cmp(string x,string y){
        if(x.length()==y.length()){
            return x<y;
        }else{
            string a,b;
            a=x;
            b=y;
            while((a.length()<b.length())) a+=x[0];
            while((a.length()>b.length())) b+=y[0];
            return a<b;
        }
    }*/

    最好和这道题一起看,觉得挺有意思UVA - 11729 Commando War
         一道看起来很简单,写起来有点痛苦,最后解法比较有趣的题目。据说是一道面试题的改编。
         题目给你一些数字的片段(number segments),所以应当用string存储而不是int,希望拼接之后能拼出的最小的数字,这是一道很神奇的题目,我分类讨论分了很多,最后突然发现它的最终解法无比简洁。
         其实就是一个序的关系,所有的组合有n!种,(像"所谓组出最小数其实是获得字典序最小的拼接方式"这种废话我就不说了)。假设我们获得了其中的一个组合,然后又两个相邻的数字片段a,b。然后我们就要想,把a和b交换能不能使整个序列变小呢?这个问题的其实等价于b+a 是否小于a+b(此处"+"为连接符),也就是说对于这样一个序列,如果某两个相邻的元素之间发生交换可以使得整个序列的值变小,我们就应该坚决的交换啊,所以这里定义一个新的序,用<<来表示,若a+b < b + a 则a应当在b前面,即a << b。然后呢,这种序是满足传递性的若a<<b ,b << c,则a<<c,所以迭代到最后,我们就会获得一个任何两个相邻元素都不能交换的局面,也就是所谓的答案。
         这样一来我们的算法就有了,比较每两个相邻的元素,如果交换可以使得整个序列变大,就交换之,直到最后没有任何两个值之间能进行交换,啊,这不就是传说中的Bubble_Sort吗,真是一个令人激动的结论啊。对序列按照之前定义的序进行排序,如此就好了。

    注意点:

     因为字符串可能前面有0,这些要移除掉(用s.erase(s.begin())就可以了~嗯~string如此神奇~~)。输出拼接后的字符串即可。
    注意:如果移出了0之后发现s.length() == 0了,说明这个数是0,那么要特别地输出这个0,否则会什么都不输出~

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    string a[10005];
    bool cmp(string x,string y){
        return x+y<y+x;
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        sort(a+1,a+1+n,cmp);
        string s="";
        for(int i=1;i<=n;i++){
            s+=a[i];
        }
        while(s[0]=='0'){
            s.erase(s.begin());
        }
        if(s.size()) cout<<s;
        else cout<<"0";
        return 0;
    }
  • 相关阅读:
    MySQL简单实现多字段模糊查询【转】
    PHP检测URL格式是否正确域名地址是否有效【转】
    php如何判断IP为有效IP地址【转】
    PHP isset() 函数使用【转】
    php生成唯一随机码【转】
    php判断一个值是否在数组中【转】
    Win10系统gpedit.msc文件找不到,如何解决【转】
    B
    【金色】种瓜得瓜,种豆得豆 Gym
    J
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/11430677.html
Copyright © 2011-2022 走看看