首页 > 代码库 > POJ 1780 Code

POJ 1780 Code

记录欧拉路径。


题意很难懂。英语渣,翻译半天不得要领。看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]);
}