题目描述
Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:
1. 这个数是回文的。
2. 不能有前导 0。
注:假设这个数字长度是 LL,那么这个数是回文的当且仅当对于任意的 i\in [1,L]i∈[1,L],第 ii 位的数码和第 L-i+1L−i+1 位的数码相同。
快来帮帮 Froggy 吧!
输入描述:
一行 10 个自然数,分别表示数码 0\sim 90∼9 的出现次数。
输出描述:
如果无解,只输出 “-1”。(不含引号)
否则,输出一个数表示最小的解。
示例1
输入
复制
0 2 4 2 0 2 0 0 0 0
输出
复制
1223553221
示例2
输入
复制
1 1 4 5 1 4 0 0 0 0
输出
复制
-1
示例3
输入
复制
4 0 2 3 0 0 0 2 0 0
输出
复制
20037373002
示例4
输入
复制
2 0 0 0 0 0 0 0 0 1
输出
复制
-1
说明
注意不能有前导 0。
示例5
输入
复制
1 0 0 0 0 0 0 0 0 0
输出
复制
0
备注:
保证输入的所有数都不超过 1010,且至少有一个数大于 00。
思路:这道题的思路其实就是把有前导零的情况和奇数的个数大于1情况排除,如果只有一个数(n==1)直接输出这个数,排除之前情况剩下的都是可以拼装回文数的,进行回文数的拼装,先写第一个和最后一个防止前导零的出现,之后对后面进行拼装就行了
AC代码:(记得多看一下注释)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int a[10];
char b[1005];
int main(int argc, char** argv) {
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int num=0,n=0;
for(int i=0;i<10;i++){
cin>>a[i];
if(a[i]%2!=0){
num++; //记录(0-9)有奇数的个数
// wo=i;
}
n+=a[i];
}
//只有一个数
if(n == 1){
for(int i = 0; i < 10; i++){
if(a[i]){
cout << i << endl;
return 0;
}
}
}
// int flag=0,p=-1;
if(num > 1 || n - a[0] <= 1 ){
//个数为奇数的数大于一,有前导0的情况(a[0]的数量等于n-1)
cout << "-1" << endl;
return 0;
}
int k=1;
if(a[0]%2!=0){
b[n/2]='0';
}
int n1=a[0]/2;
//记录第一个和最后一个的值
for(int i=1;i<10;i++){
if(a[i]){
if(a[i] == 1){
continue;
}
b[0] = i + '0';//前半部分赋值
b[n-1] = i + '0'; //后半部分赋值
a[i] -= 2;
break;
}
}
//记录(1到n-2)中间的值
int temp=1;//记录需要填入目标数组位置变化
for(int i=0;i<10;i++){
if(a[i]){
if(a[i]%2!=0){//把奇数的数字放在中间
b[n/2] = '0' + i;
}
int j;
for(j = 0; j < a[i] / 2; j++){
b[temp+j] = i + '0';//前半部分赋值
b[n-temp-j-1] = i + '0'; //后半部分赋值
}
temp += j;//向后移动a[i]-1个位置
}
}
for(int i=0;i<n;i++){
cout<<b[i];
}
//cout<<endl;
return 0;
}