题目传送门
题意是:一个数字,如果他任意两个相邻位上的数字差的绝对值不超过1,那么这个数字就合法,给你一个k,找出第k小的合法数字。
思路:首先,对于个位数,全都是合法数字,然后考虑两位数的情况,我们可以用原来确定是9个个位数作为两位数的十位,比如1,那么由1发展来的两位数就可以是10、11、12,三位数又可以由两位数发展过来,比如10可以发展成100、101,画个图就发现这很像独立的9颗树,树根分别是1、2、3、4、5、6、7、8、9,我们可以用0作为根把这个森林连起来,看做一棵树来处理。我们在知道建树的逻辑后只需要层次遍历这棵树,找到第k个的时候回溯输出就行了。
因为涉及回溯输出,这里用链表实现多叉树很方便。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int eps=1e-6;
typedef long long ll;
typedef unsigned long long ull;
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
#define null NULL
struct node
{
node *pre;
node *child[10];
int num;
};
void init(node *&L)
{
L=new node;
L->pre=null;
for(int i=1;i<=9;i++)
{
L->child[i]=null;
}
}
signed main()
{
IOS;
int k;
cin>>k;
node *L;
init(L);
int cnt=0;
queue<node *>q;
for(int i=1;i<=9;i++)
{
node *p;p=new node;
L->child[i]=p;p->num=i;p->pre=L;
q.push(p);
cnt++;
if(cnt==k)
{
cout<<i<<endl;
return 0;
}
}
while(!q.empty())
{
node *p=q.front();
q.pop();
for(int i=max(0LL,p->num-1);i<=min(9LL,p->num+1);i++)
{
node *t=new node;
t->num=i;t->pre=p;
p->child[i]=t;
q.push(t);
cnt++;
if(cnt==k)
{
stack<int>s;
node *tt;tt=t;
while(tt!=L)
{
s.push(tt->num);
tt=tt->pre;
}
while(!s.empty())
{
cout<<s.top();s.pop();
}
cout<<endl;
return 0;
}
}
}
}