zoukankan      html  css  js  c++  java
  • UVA 10905 Children's Game

    UVA_10905

        我们不妨先定义一个大于号“》”:对于字符串a,b,如果有a》b就表示ab的字典序要大于ba的字典序。

        假设:如果有a》b,且b》c,那么就有a》c。

        如果这个假设满足,那么N个字符串就可以按》的关系排成一排,这时拼成的字符串就是字典序最大的(同时也是值最大的,因为最终拼成的字符串的长度是一定的,所以值的大小关系和字典序的大小关系是相同的)。

        下面用反证法证明为什么这样拼成的字符串的字典序一定是最大的:如果最终拼成的字符串不是这样的,那么就一定存在相邻的两个字符串a、b不满足a》b,那么我们可以交换a、b的顺序,这样得到的结果不会变得更差。于是我们不停的交换不满足a》b的两个相邻的a、b,直到变成N个字符串是按》的关系排成一排为止,这样得到的结果不会变得更差。因此,可以保证这样拼成的字符串字典序是最大的。

        当然,这样的贪心思路是依赖于上文中字体加粗的“假设”部分的。如果不能证明这个假设是正确的,那么就没办法说明这个贪心是正确的(比如如果存在a》b,b》c且c》a,那么对于acb来讲,到底是变成cab更好,还是变成abc更好呢?这恐怕就说不清了吧……)。但是我暂时没证明出“假设”的部分,稍后补上……

        *上述讨论默认N个字符串是不同的,如果有相同的字符串,处理和证明的过程也基本相同,所以就没再讨论有相同字符串的情况了。

    #include<stdio.h>
    #include<string.h>
    #include<string>
    #include<algorithm>
    #include<iostream>
    std::string a[110];
    bool cmp(std::string a, std::string b)
    {
        return (a + b).compare(b + a) > 0;
    }
    int main()
    {
        int N;
        while(scanf("%d", &N), N)
        {
            for(int i = 0; i < N; i ++) std::cin >> a[i];
            std::sort(a, a + N, cmp);
            for(int i = 0; i < N; i ++) std::cout << a[i];
            std::cout << std::endl;
        }
        return 0;
    }
  • 相关阅读:
    【LeetCode】17. Letter Combinations of a Phone Number
    【LeetCode】16. 3Sum Closest
    【LeetCode】15. 3Sum 三个数和为0
    【LeetCode】14. Longest Common Prefix 最长前缀子串
    【LeetCode】13. Roman to Integer 罗马数字转整数
    【LeetCode】12. Integer to Roman 整型数转罗马数
    【LeetCode】11. Container With Most Water
    【LeetCode】10. Regular Expression Matching
    Models of good programmer
    RSA Algorithm
  • 原文地址:https://www.cnblogs.com/staginner/p/2760486.html
Copyright © 2011-2022 走看看