POJ 1270 Following Orders DFS 搜索

16 篇文章 0 订阅
1 篇文章 0 订阅

题意:

        输入数据有两行,第一行给你由26个单个小写字母表示的变量,第二行给出成对的变量如(x,y),表示x要在y前面.然后要你输出所有可能的变量序列且满足第二行的顺序约束.如果存在多解,按字典序从小到大输出所有结果.

#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;  
}

写法二:拓扑排序

#include<cstdio>  
#include<cstring>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
const int MAXN=30;  
char a[MAXN];  
char temp[200];  
int map[MAXN][MAXN];  
bool vis[MAXN];  
int id[MAXN],to[MAXN],route[MAXN];  
int len;  
  
void topsort(int cur)  
{  
    if(cur==len)  
    {  
        for(int i=0;i<len;i++)  
            printf("%c",a[ route[i] ]);  
        printf("\n");  
        return;  
    }  
    for(int i=0;i<len;i++)  
    {  
        if(!vis[i] && !to[i])  
        {  
            for(int j=0;j<len;j++)     //与之相连的度减1  
                if(map[i][j])  
                    to[j]--;  
            vis[i]=true;  
            route[cur]=i;  
            topsort( cur+1 );  
              
            for(int j=0;j<len;j++)  
                if(map[i][j])  
                    to[j]++;  
            vis[i]=false;  
        }  
    }  
}  
  
int main()  
{  
    int kase=0;  
    while(gets(temp)!=NULL)  
    {  
        if(kase)  
            printf("\n");  
        kase++;  
  
        memset(id,-1,sizeof(id));  
        memset(map,0,sizeof(map));  
        memset(vis,0,sizeof(vis));  
        memset(to,0,sizeof(to));  
  
        len=0;  
        for(int i=0;temp[i]!='\0';i++)    
            if(temp[i] !=' ')  
                a[len++]=temp[i];  
          
          
        sort(a,a+len);  
        for(int i=0;i<len;i++)         //进行编号,当然你也可以直接用STL的map  
            id[ a[i]-'a']=i;  
  
        gets(temp);  
        bool flag=0;  
        int x;  
        for (int i = 0; temp[i]!='\0'; i++)  //建立图不是i+4就好,狂WA,后看DISCUSS,跟着改了就AC了  
        {  
            if (temp[i] == ' ')   
                continue;  
            if (!flag)   
                x =temp[i] - 'a';  
            else   
            {  
                map[ id[ x ] ][ id[ temp[i]-'a'] ]=1;  
                to[ id[temp[i]-'a']]++;  
            }  
            flag = !flag;  
        }  
        topsort(0);  
    }  
    return 0;  
}  



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值