记录欧拉路径。
题意很难懂。英语渣,翻译半天不得要领。看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]); }
POJ 1780 Code
时间: 2024-11-05 21:33:32