刷题记录:牛客NC212226回文数

传送门:牛客

Froggy 分别给出 10 个数码的出现次数,你需要找到一个由这些数码组成的最小的数,满足:
1. 这个数是回文的。
2. 不能有前导 0。
注:假设这个数字长度是 LL,那么这个数是回文的当且仅当对于任意的 i\in [1,L]i∈[1,L],第 ii 位的数码和第 L-i+1L−i+1 位的数码相同。
快来帮帮 Froggy 吧!
输入:
0 2 4 2 0 2 0 0 0 0
输出:
1223553221

这道题目表面上十分的简单,或者认为只是一道回文数的题目(当初我也是这么认为的,然而没想到的是一道比较恶心的大模拟(至少我是这么认为的),有着很多的细节问题)

在这里插入图片描述
主要思路:首先要保证是回文的,要保证的第一点是奇数个的数字一定小于等于一个,这样才能保证奇数个的数字在正中间时是符合条件的

当判断是否符合时,题目中要输出字典序最小的,又不能有前导零,所以我的解决方法是从左往右枚举第一个不是0的且是偶数的数字,然后输出这个数字一次,然后在输出全部的0,最后再输出该数字剩下的个数,同时要判断有无奇数个的数字,如果有的话要将其剩下的一个放在正中间,当然这种方法又要特判有没有0的存在,然后代码的语句就非常的冗长

下面是具体的实现代码,十分冗长但是逻辑清晰(建议自己实现,不然看起来头都大了)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define maxn 1000000
int a[20];
int main() {
	memset(a,0,sizeof(a));
	int oushu=0,jishu=0;
	for(int i=0;i<=9;i++){
		a[i]=read();
		if(a[i]%2==0&&a[i]!=0) oushu++;
		else if(a[i]%2==1) {
			jishu++;
		}
	}
	if(jishu>1){
		cout<<"-1";
		return 0;
	}
	if(jishu==1) {
		if(oushu==0){
			for(int i=0;i<=9;i++) {
				if(a[i]%2==1) {
					for(int j=1;j<=a[i];j++) cout<<i;
				}
			}
		}
		else {
			int pos;
			for(int i=0;i<=9;i++) {
				if(a[i]%2==1) {
					pos=i;break;
				}
			}
			if(a[0]==0) {
				for(int i=1;i<=9;i++) {
					if(a[i]!=0) {
						for(int j=1;j<=a[i]/2;j++) cout<<i;
					}
				}
				cout<<pos;
				for(int i=9;i>=1;i--) {
					if(a[i]!=0) {
						for(int j=1;j<=a[i]/2;j++) cout<<i;
					}
				}
			}else {
				if(oushu==1&&a[0]>0&&a[pos]<3) {
					cout<<"-1";
					return 0;
				}  
				int ppos=-1;
				for(int i=1;i<=9;i++) {
					if(a[i]>1) {
						if(ppos==-1) {
							cout<<i;
							for(int j=1;j<=a[0]/2;j++) cout<<0;
							for(int j=1;j<=a[i]/2-1;j++) cout<<i;
							ppos=i;
						}else {
							for(int j=1;j<=a[i]/2;j++) cout<<i;
						}
					}
				}
				cout<<pos;
				for(int i=9;i>=1;i--) {
					if(a[i]>1) {
						if(ppos==i) {
							for(int j=1;j<=a[i]/2-1;j++) cout<<i;
							for(int j=1;j<=a[0]/2;j++) cout<<0;
							cout<<i;
						}else {
							for(int j=1;j<=a[i]/2;j++) cout<<i;
						}
					}
				}
			}
		}
	}else {
		if(a[0]==0) {
			for(int i=1;i<=9;i++) {
				if(a[i]%2==0&&a[i]!=0) {
					for(int j=1;j<=a[i]/2;j++) cout<<i;
				}
			}
			for(int i=9;i>=1;i--) {
				if(a[i]%2==0&&a[i]!=0) {
					for(int j=1;j<=a[i]/2;j++) cout<<i;
				}
			}
		}else {
			if(oushu==1) {
				cout<<"-1";
				return 0;
			}
			int ppos=-1;
			for(int i=1;i<=9;i++) {
				if(a[i]%2==0&&a[i]!=0) {
					if(ppos==-1) {
						cout<<i;
						for(int j=1;j<=a[0]/2;j++) cout<<0;
						for(int j=1;j<=a[i]/2-1;j++) cout<<i;
						ppos=i;
					}else {
						for(int j=1;j<=a[i]/2;j++) cout<<i;
					}
				}
			}
			for(int i=9;i>=1;i--) {
				if(a[i]%2==0&&a[i]!=0) {
					if(ppos==i) {
						for(int j=1;j<=a[i]/2-1;j++) cout<<i;
						for(int j=1;j<=a[0]/2;j++) cout<<0;
						cout<<i;
					}else {
						for(int j=1;j<=a[i]/2;j++) cout<<i;
					}
				}
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值