【問題描述】
設有n(n<=20)個正整數,將他們連接成一排,組成一個最大的多位整數。
例如n=3時,3個整數13,312,343,連接成的最大整數爲34331213。
又如:n=4時,4個整數7,13,4,246連成的最大整數爲7424613。
【輸入格式】
第1行一個整數n,第2行n個整數數
【輸出格式】
連接成的多位數。
【輸入樣例】
4
7 13 4 246
【輸出樣例】
7424613
【數據範圍】
n<=20
題意:很簡單,就是給你一些正整數,要求你把這些正整數重新組合成新的一個整數,要求這個新的整數儘量大。
算法:貪心(排序有點難想啊);
這個題看起來並不難,可能很多人覺得,將每個整數讀入一個字符串數組。然後通過比較字符串的大小排序就能確定輸出整數的順序。我也是這樣做的,結果只得了75分。錯了一組數據:
6
321 32 407 135 13 217
正確答案 4073232121713513
而我的輸出 4073213221713513 321和32的順序倒了
所以這樣想是有漏洞的,因爲可能存在一個串的前綴和另一個相等的情況,在這種情況下,顯然兩者中更長的串的ASCII碼更大,然而卻不一定要選更長的串。
因爲最後答案整數的位數是定了的,如果把前面ASCII碼大的串先加入,由於調整位置時原數字不能拆分,所以會佔更多的高位。而這些多出來高位的值可能還不如加入小的串後前面幾位的值。
整理了一下老師講的和網上的算法:
正確排序1:如果一個字符串是第二個字符串的前綴的話,則將長串與第一個字符串相同的部分截去,將剩下的繼續比較,當出現有字串長度爲0的時候特殊處理。(見代碼1)
正確排序2:設兩個待比較的字符串爲s1,s2,那麼其實要最優只需要比較strcat(s1,s2)和strcat(s2,s1)即可。(代碼2)
<代碼1>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<cstdlib>
#define maxn 25
using namespace std;
int n;
string num[maxn];
bool cmp(const string& s1, const string& s2)//比較s1和s2,在相同位時如果某個字符串數字較大就把它排在前
{
if(s1.size()==0) return false;//s1不存在數字就排在後
if(s2.size()==0) return true;//s2不存在數字就把s1排前面
int minsz=min(s1.size(),s2.size());
if(strncmp(s1.c_str(),s2.c_str(),minsz)==0)
{
if(minsz==s1.size())
{
return cmp(s1,s2.substr(minsz));
}
else
{
return cmp(s1.substr(minsz),s2);
}
}
else
return s1>s2;
}
int main()
{
//freopen("my.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
cin>>num[i];
sort(num+1,num+n+1,cmp);
for(int i=1;i<=n;i++)
cout<<num[i];
return 0;
}
<代碼2>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<cstdlib>
#define maxn 25
using namespace std;
int n;
struct data
{
char s[100];
}A[maxn];
bool cmp(data a,data b)
{
char t1[100],t2[100];
strcpy(t1,a.s);
strcat(t1,b.s);
strcpy(t2,b.s);
strcat(t2,a.s);
if(strcmp(t1,t2)>0)return 1;
return 0;
}
int main()
{
//freopen("my.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",A[i].s);
sort(A+1,A+n+1,cmp);
for(int i=1;i<=n;i++)
printf("%s",A[i].s);
return 0;
}