记录欧拉路径。
题意很难懂。英语渣,翻译半天不得要领。看PDF的中文才知道题意。
题意:给一个 N (1<=N<=6)找出字典序最短的所有数字组合都出现的序列。
给出了N=2 的例子。就拿这个说明,太长就说前面的。
00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990
00 出现了,01出现,然后 10,02,20,03,30,04,40,05,50,06,60,07,70,08,80,09。
90不能在这里出现。因为0开头的已经全部出现了,如果这儿接0不能保证最短。91,(10miss)11,12,
前一个数字的尾必须作为下一个数字的首。
如果是多位N=6。前一个数字除了首位一个,剩下五个都必须作为下一个的头。这样排下去。
最后长度为 10^N+N-1。
取自PDF:
n 位数有10n 种编码方案(即10n 组数),要使得一个数字序列包含这10n 组n 位数,且序列的长
度最短,唯一的可能是每组数出现一次且仅一次、且前一组数的后n-1 位是后一组数的前n-1 位,
这样10n 组数各取1 位,共10n 位,再加上最后一组数的后n-1 位,总位数是10n + n - 1。
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<stack>
#include<iostream>
#include<list>
#include<set>
#include<cmath>
#define INF 0x7fffffff
#define eps 1e-6
#define LL long long
using namespace std;
#define M 100000
char str[7][M*10];
int l[M];
stack<int>s;
char ans[M * 10];
int a;
void dfs( int v, int m )
{
int w;
while ( l[v] < 10 )
{
w = v * 10 + l[v];
l[v]++;
s.push(w);
v = w % m;
}
}
int main( )
{
int n, m, i, v;
strcpy(str[1],"0123456789");
for(int nn=2; nn<=6; nn++)
{
n=nn;
while(!s.empty())s.pop();
a = 0, v=0;
m = pow( 10, double( n - 1 ) );
for ( i = 0; i < m; i++ ) l[i] = 0;
dfs( v, m );
while(!s.empty())
{
v=s.top();
s.pop();
ans[a++] = v % 10 + '0';
v /= 10;
dfs( v, m );
}
int cot=0;
for ( i = 1; i < n; i++ )
str[nn][cot++]='0';
while (a)
str[nn][cot++]=ans[--a];
str[nn][cot]='\0';
}
while(scanf("%d",&n),n)
puts(str[n]);
}