Code

忙了好久,终于搞定了,每次将不会的题琢磨完了,都感觉是一次小小的进步,庆祝一下下。。呵呵

首先是建图,题意要求所有的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;
}
posted on 2010-10-31 16:09  ylfdrib  阅读(1268)  评论(1编辑  收藏  举报