【9603】最大整数

来源:互联网 发布:算法统宗一百馒头 编辑:程序博客网 时间:2024/06/05 03:42

Time Limit: 3 second
Memory Limit: 2 MB

【问题描述】

设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数。 例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613

【输入格式】

两行。第一行为一个整数(n<=1000),表示正整数的个数。第二行n个正整数

【输出格式】

仅一行,联接成的多位数

【输入样例】

3 13 312 343

【输出样例】

34331213

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=9603

【题解】

把所有的字符串按照字符串比较的规则从大到小排序然后再一个一个接上去的方法是错的;有反例
321 32
显然
32321>32132
这是因为32是321的前缀;
这个时候需要比较那个较长的字符串的第一个和较短的字符串不同的位置的数字和它的第1个数字的大小;
在本例中第一个不同位置为s2[3]=1,而s2[1]=3;
因为s2[1]>s2[3]所以把较短的32放在前面更优一点;
因为s1前面部分都和s2一样;
s1如果放在s2前面那么整个数字第3位是3(前面两个数字一样);
s2如果放在s1前面那么真个数字第3位是1(也即较长那个数字的第3位);
这种情况排除掉之后就能按照正常的思路搞了;
我们可以一个一个数字地往前i-1个数字里面添加一个数字;然后成为i个数字;
一开始把所有的字符先按照长度降序排一下;可以避免很多判断;

【完整代码】

#include <cstdio>#include <cstdlib>#include <cmath>#include <set>#include <map>#include <iostream>#include <algorithm>#include <cstring>#include <queue>#include <vector>#include <stack>#include <string>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define LL long long#define rep1(i,a,b) for (int i = a;i <= b;i++)#define rep2(i,a,b) for (int i = a;i >= b;i--)#define mp make_pair#define pb push_back#define fi first#define se secondtypedef pair<int,int> pii;typedef pair<LL,LL> pll;void rel(LL &r){    r = 0;    char t = getchar();    while (!isdigit(t) && t!='-') t = getchar();    LL sign = 1;    if (t == '-')sign = -1;    while (!isdigit(t)) t = getchar();    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();    r = r*sign;}void rei(int &r){    r = 0;    char t = getchar();    while (!isdigit(t)&&t!='-') t = getchar();    int sign = 1;    if (t == '-')sign = -1;    while (!isdigit(t)) t = getchar();    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();    r = r*sign;}const int MAXN = 1e3+100;const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};const double pi = acos(-1.0);int n;string s1[MAXN];int f(string s1,string s2){    int len1=s1.size(),len2 = s2.size();    if (len1>len2)        return -1;    len1 = min(len1,len2);    rep1(i,0,len1-1)        if (s1[i]!=s2[i])            return -1;    if (len1==len2)        return -1;    else        return len1;}bool cmp(string a,string b){    int len1 = a.size(),len2 = b.size();    return len1>len2;}int main(){/*    s1[1]="321";s1[2]="32";    printf("%d\n",s1[1]>s1[2]);    return 0;    */    //freopen("F:\\rush.txt","r",stdin);    rei(n);    rep1(i,1,n)        cin >> s1[i];    sort(s1+1,s1+1+n,cmp);    rep1(i,1,n)    {        int j = 1;        while (j<=i-1)        {            //int len1 = s1[j].size(),len2=s1[i].size();            //len1 >= len2 is always yes;            if (s1[j]>s1[i])                {                    int t = f(s1[i],s1[j]);                    if (t==-1)                    {                        j++;                        continue;                    }                    if (s1[j][t]>s1[j][0])                    {                        j++;                        continue;                    }                    else                        break;                }                else                    if (s1[j]<s1[i])                        break;        }        string x=s1[i];        rep2(k,i,j+1)            s1[k] = s1[k-1];        s1[j] = x;    }    string s ="";    rep1(i,1,n)        s+=s1[i];    cout << s<<endl;    return 0;}
0 0