Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:
1. 这个数是回文的。
2. 不能有前导 0。
注:假设这个数字长度是 LLL,那么这个数是回文的当且仅当对于任意的 i∈[1,L]i\in [1,L]i∈[1,L],第 iii 位的数码和第 L−i+1L-i+1L−i+1 位的数码相同。
快来帮帮 Froggy 吧!
输入描述:
一行 10 个自然数,分别表示数码 0∼90\sim 90∼9 的出现次数。
输出描述:
如果无解,只输出 “-1”。(不含引号)
否则,输出一个数表示最小的解。
示例1
输入
0 2 4 2 0 2 0 0 0 0
输出
1223553221
输入
1 1 4 5 1 4 0 0 0 0
输出
-1
输入
4 0 2 3 0 0 0 2 0 0
输出
20037373002
输入
2 0 0 0 0 0 0 0 0 1
输出
-1
说明
注意不能有前导 0。
输入
1 0 0 0 0 0 0 0 0 0
输出
0
备注:
保证输入的所有数都不超过 101010,且至少有一个数大于 000。
分析:
1.如果有超过一个以上有奇数个数,说明不可能构成回文数。
2.如果零个数只有一个,其他数字没有,直接输出0。
3.前导零不行,并且满足字典序最小。
4.注意2 0 0 5 0 10 0 0 0 0这个例子。
代码实现:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll a[10];
void solve()
{
ll t=0;
string s="";
for(ll i=0;i<10;i++)
{
cin>>a[i];
if(a[i]%2!=0)
{
t++;
}
if(t>1)//如果一个以上的数个数为奇数个,说明无法构成回文
{
cout<<"-1";
return ;
}
}
ll qd=-1,tm=0;
for(ll i=1;i<10;i++)
{
if(a[i]>=2)//因为不能有前导0,所有要找0放哪
{
qd=i;
break;
}
if(a[i]==0)
tm++;
}
if(tm==8&&a[0]==0)
{
}
else if(tm==9&&a[0]==1)
{
cout<<'0';
return ;
}
else if(qd==-1)
{
cout<<"-1";
return ;
}
ll res=0;
for(ll i=1;i<10;i++)
{
ll j=a[i]/2;
if(j>=1)
{
s=s+string(1,'0'+i);
if(qd==i)//因为0最小的特殊性,只要不为前导0,则靠前输出
s=s+string(a[0]/2,'0');
s=s+string(j-1,'0'+i);
}
}
string s1=s;
for(ll i=0;i<10;i++)
{
if(a[i]%2!=0)
{
s=s+string(1,'0'+i);//最中间的特殊处理
break;
}
}
reverse(s1.begin(),s1.end());//反转后接到一起
s=s+s1;
cout<<s;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t=1;
while(t--)
solve();
return 0;
}