poj 1780 Code 有向图输出欧拉路径+非递归深搜

题意:

给一个数字n,n位数的密码最多有10^n个,现在要求一个字符串包含这10^n个串恰好各一次且字典序最小。

分析:

把每个可能的串看作边,构成这个串的两个n-1位数看作点则转化为欧拉路径问题,比如n==4时有u=423,v=239,e=4239.这题用递推会暴,要使用dfs的非递归写法:while(1){

if(栈中结点无法再扩展)将栈中结点放入close表,出栈(栈为空退出);while(栈顶结点可以扩展)扩展,将新节点放在栈顶 }}。

代码:

#include <iostream>
using namespace std;
const int maxN=1000024; 
struct Edge
{
	int v,id,next;
}edge[maxN*10];
struct Node
{
	int v,e;
}s[maxN];
int n,e,top,st;
int pow[8]={1,10,100,1000,10000,100000,1000000};
int head[maxN];
int stack[maxN];
int vis[maxN];
int path[maxN];
void addedge(int u,int v,int id)
{
	edge[e].v=v;edge[e].id=id;edge[e].next=head[u];
	head[u]=e++;
}

void process()
{
	Node p;
	memset(vis,0,sizeof(vis));
	top=0,st=0;
	int t=head[0];
	p.v=0,p.e=t;
	s[st++]=p;
	vis[edge[t].id]=1;
	while(1){
		if(t==-1){
			Node y=s[st-1];
			path[top++]=edge[y.e].id;
			st--;
			if(st==0)
				break;	
		}	
		Node x=s[st-1];
		t=head[x.v];
		while(t!=-1){
			if(!vis[edge[t].id]){
				vis[edge[t].id]=1;
				p.v=edge[t].v,p.e=t;
				s[st++]=p;
				break;	
			}
			t=edge[t].next;
		}
	}
}

void solve()
{
	if(n==1){
		printf("0123456789\n");
		return ;
	}
	memset(head,-1,sizeof(head));
	e=0;
	int i,j,len=pow[n-1];
	for(i=0;i<len;++i){
		int tmp=i%(len/10);
		tmp*=10;;
		for(j=9;j>=0;--j)
			addedge(i,tmp+j,i*10+j);		
	}
	process();
	for(int i=top-1;i>=1;--i)
		printf("%d",path[i]/len);
	printf("%d\n",path[0]);
	return ;
}

int main() 
{

	while(scanf("%d",&n)==1&&n)
		solve();
	return 0;	
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值