题目分析
我们首先翻译一下题目,玩家会获得n个正整数(n<=50),进行排列组合。例如四个整数123,124,56,90,可以生成4*3*2*1共计24种组合,其中显然最大组合情况为9056124123。
这很容易想到应该将数值最大的数放在权值的高位。所以我们要做的就是给n个正整数排序,排序的规则的从第一位开始比较,从大到小,依次是第二位第三位,如果没有下一位,视为目前最大,排在前面。
一开始我认为本题数据量很小,对于排序规则的实现部分,就可以大胆的随意的去使用蛮力,结果超时。
#include<iostream>
using namespace std;
int getk(int num,int k)
{
if (num == 0)
return 0;
while (num >=k*10)
num /= 10;
if(k==1)
return num;
else
return num%((k-1)*10);
}
int main()
{
int n;
while(cin>>n)
{
if(n==0)
return 0;
int a[n];
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n-i-1;j++)
{
for(int k=1;k<=32;)
{
if(getk(a[j],k)<getk(a[j+1],k))
{
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
break;
}
if(getk(a[j],k)==getk(a[j+1],k))
k++;
}
}
}
for(int i=0;i<n;i++)
{
cout<<a[i];
}
cout<<endl;
}
return 0;
}
我回想了一下解题思路,发现确实没想到什么合适的算法来优化,不过在写上面一段排序规则的时候,我想到了字符串比较函数,这两个高度相似,为此我还去搜了一下关于正整数有没有类似字符串的处理函数。
说到这已经恍然大悟了,完全可以将数字当做字符串处理。如下。
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n==0)
return 0;
string a[n];
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(a[j]<a[j+1])
{
string temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<n;i++)
{
cout<<a[i];
}
cout<<endl;
}
return 0;
}
这个时候运行会发现一个致命的问题。我们将如果没有下一位,视为目前最大,但是对于“a”,是小于“ad”的,这个例子中,第一个字符串没有第2位字符相当于null,null的ascll值等于0,而‘d’的ascll的值为100,所以后者大于前者。而我们需要将“9”视为排在“90”前面。
那么改为字符串处理的问题出现了,我们该怎么解决呢?这里我采用了参考的一个思路。我们如果使用sort函数对字符串数组a排序,cmp的代码是比较a[i]和a[j]的大小,这里我们不妨将cmp函数改为a[i]+a[j]和a[j]和a[i]比较大小,这样就有效的解决了前面那个问题同时符合我们的逻辑初衷。
这里解释一下为什么要这么写cmp,因为我们想求的就是正整数组合之后的结果最大,所以说这个解法符合我们的逻辑初衷。对于字符串string,使用+就可以连接成为一个字符串,从而比较“990”和“909”哪一个更大。
ac代码
#include<iostream>
#include<algorithm>
using namespace std;
int cmp(string a,string b)
{
return a+b>b+a;
}
int main()
{
int n;
while(cin>>n)
{
if(n==0)
return 0;
string a[n];
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
cout<<a[i];
cout<<endl;
}
return 0;
}