忙了好久,终于搞定了,每次将不会的题琢磨完了,都感觉是一次小小的进步,庆祝一下下。。呵呵
首先是建图,题意要求所有的n位数编码成一个数字串,每个n位数只出现一次,可以把n位数看成边,那么可以把它的前n-1位看成点A,后n-1一位看成点B,那么它就是A->B的一条边了,这样我们就可以对10^(n - 1)个点建图,每个节点对另外10个点有边,找一次欧拉回路就行了。
这题有一难点,要求按最小字典序输出,我用邻接表存的边,然后对于每个点的链表是按字典序建的边,这样再用圈套圈算法,然后逆序输出,就可以求的最小序结果了。
还有个一个问题,如果递归写的话,就会系统栈爆栈,导致RE,所以需要我们改成非递归的形式,这点让我郁闷了好久。。 不过还是让我给改出来了,收获!让我对系统栈又有了更深的理解。
//============================================================================
// Description : 圈套圈算法,逆序输出欧拉回路
//============================================================================
#include <iostream>
#include<stdio.h>
#include<string.h>
#define NN 1000020
using namespace std;
typedef struct node{
//int u;
int v;
int vis;
struct node *nxt;
}NODE;
NODE *Link[NN / 10];
NODE edg[NN];
NODE *sta[NN]; // 模拟系统栈
int idx, kind, n, top;
int stk[NN];
void Init(){
memset(Link, 0, sizeof(Link));
idx = top = 0;
}
void Add(int u, int v){
//edg[idx].u = u;
edg[idx].v = v;
edg[idx].vis = 0;
edg[idx].nxt = Link[u];
Link[u] = edg + idx++;
}
void dfs(int u){ // 递归形式
for (NODE *p = Link[u]; p; p = p->nxt){
if(!p->vis){
p->vis = 1;
Link[u] = p->nxt;
dfs(p->v);
stk[++top] = p->v % 10;
}
}
}
void dfs1(int u){ // 非递归形式
int top0 = 0;
NODE *p;
sta[++top0] = Link[u];
while(top0){
for (p = sta[top0]; p; p = p->nxt){
if(!p->vis){
p->vis = 1;
sta[top0] = p; // 递归进入下一层的时候,先保存入口
sta[++top0] = Link[p->v]; //进入下一层
Link[u] = p->nxt; // 更改链表头指针
u = p->v; // 这点很重要,每次进入下一次递归的时候需要更改,否则不变
break;
}
}
if(p == NULL){
top0--;
if(top0 == 0) break;
stk[++top] = sta[top0]->v % 10;
sta[top0] = sta[top0]->nxt;
}
}
}
void Solve(){
int i;
dfs1(0);
for (i = 1; i < n; i++){
printf("0");
}
for (i = top; i >= 1; i--){
printf("%d", stk[i]);
}
puts("");
}
int main() {
int i, j;
while(scanf("%d", &n) != EOF){
if(n == 0) break;
if(n == 1){
puts("0123456789");
continue;
}
kind = 1; // kinds or number
for (i = 1; i < n; i++){
kind = kind * 10;
}
Init();
int mod = kind / 10;
for (i = 0; i < kind; i++){
int tmp = i % mod;
tmp *= 10;
for (j = 9; j >= 0 ; j--){
//if(tmp + j != i){
Add(i, tmp + j);
//}
}
}
Solve();
}
return 0;
}
浙公网安备 33010602011771号