回文数(暴力)
题目描述:
Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:
- 这个数是回文的。
- 不能有前导 0。
注:假设这个数字长度是 L,那么这个数是回文的
当且仅当对于任意的
i
∈
[
1
,
L
]
i\in [1,L]
i∈[1,L],第
i
i
i 位的数码和第
L
−
i
+
1
L-i+1
L−i+1 位的数码相同。
快来帮帮 Froggy 吧!
输入描述:
一行 10 个自然数,分别表示数码 0 ∼ 9 \sim9 ∼9 的出现次数。
输出描述:
如果无解,只输出 “-1”。(不含引号)
否则,输出一个数表示最小的解。
思路:
- 可以发现对于要是回文,只允许有一个数码的个数是奇数。
- 题目后面有补充,000这一种情况是不可以的。(它含有前导0).
- 贪心添加即可。两边先放一个非0.(假如放不了,判断是否只有一个0的情况)
- 两边插入时,可以使用string操作前半段。后半段reverse即可。 (有无奇数,就是有无在中间加一个数的区别)
AC
#include <iostream>
#include <string>
#include <algorithm>
#define For(i,x,y) for(int i=(x); i<=(y); i++)
using namespace std;
int d[10];
string ans;
bool work(string &tmp){
bool fl=false;
For(i,0,9){
if(d[i]&&i){
tmp+=i+'0';
d[i]--;
fl=true;
break;
}
}
if(!fl)return false;
For(i,0,9){
if(d[i]){
For(j,1,d[i]/2)tmp+=i+'0';
}
}
return true;
}
int main()
{
int odd=0,even=0,sum=0,k=0;
For(i,0,9){
cin>>d[i];
sum+=d[i];
if(d[i]%2)odd++,k=i;
else even++;
}
string tmp;
if(sum%2==0&&odd==0){
if(!work(tmp))cout<<-1<<endl;
else {
ans+=tmp;
reverse(tmp.begin(),tmp.end());
ans+=tmp;
}
cout<<ans<<endl;
}else if(sum%2&&odd==1){
//只有奇数时,才可能是一个0 的ans。
d[k]--;
if(k==0&&sum==1)cout<<0<<endl;
else if(!work(tmp))cout<<-1<<endl;
else {
ans+=tmp;
reverse(tmp.begin(),tmp.end());
ans+=k+'0';
ans+=tmp;
}
cout<<ans<<endl;
}else cout<<-1<<endl;
return 0;
}