poj1270 拓扑排序+dfs

原文链接:https://blog.csdn.net/u013480600/article/details/30315289

1.当前被选的字母必须有效(即mark[i]==true)且当前被选的字母vis=false(即还没被选)。

2.当我们从前到后依次选择一个字母x放进topo数组的时候,我们要保证在topo数组的当前位置cnt的前面那些位置中不会出现y这种字母。其中y<x,即y被要求出现在x后面。

3.可能有人会有疑问,就算保证了x出现在它的所有后继前面,但是你没有保证z(z>x)出现在x前面啊,那如果已经选了x的时候还没选z,怎么能形成合法的序列呢?

解答:当选了x时还没选z的话,在之后的递归中,标记当前位置的cnt就不可能==n,所以dfs不会产生一个可行解,这个dfs就无疾而终了。也就是说程序会自动忽略这种非法解。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=30;
const int maxm=500;
int n;//有效字母数
int G[maxn][maxn];
int vis[maxn];
int ans[maxn];
int cnt;
bool mark[maxn];//标记当前字母出现在变量中
bool ok(int i,int cnt)//如果在ans[0,cnt-1]出现了一个本应在i后面才出现的字母,那么返回false
{
    for(int j=0;j<cnt;j++)
        if(G[i][ans[j]]) return false;
    return true;
}
void dfs(int cnt)
{
    if(cnt==n)
    {
        for(int i=0;i<n;i++)
            printf("%c",ans[i]+'a');
        printf("\n");
    }
    else for(int i=0;i<26;i++)  
		if(mark[i]&&!vis[i]&&ok(i,cnt)){
       	   	vis[i]=1;
       		ans[cnt]=i;
      	    dfs(cnt+1);
       		vis[i]=0;
    	}
}
int main()
{
    char str[1000];
    while(gets(str))
    {
        n=0;
        memset(mark,0,sizeof(mark));
        memset(G,0,sizeof(G));
        memset(vis,0,sizeof(vis));
        for(int i=0;str[i];i++)
			if(str[i]!=' ')
            	mark[str[i]-'a']=true, n++;
        gets(str);
        for(int i=0;str[i];i++)
			if(str[i]!=' '){
            	int a,b;
            	a=str[i++]-'a';
            	while(str[i]==' ')
                	i++;
            	b=str[i]-'a';
            	G[a][b]=1;
        	}
        dfs(0);//表示当前正在构造第0个位置
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值