Hdu 1181 变形课

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1181

 

看完这题首先想到的是用DFS,因为只要找到就行了,不求找到的最快方法。首先从开头字母为'b'的单词出发,目标为首尾相接,且末字母为'm'的单词。中间的搜索时的下一个链接单位自然是首尾相接的单词。

 

DFS:

#include <iostream>

#include <cstring>

#include <string>

#include <cstdio>



using namespace std;



const int maxn = 1000 + 24;

string word[maxn];

bool vis[maxn];

int pos;

int flag=0;



void dfs( string str )

{

    if( flag )

        return ;

    int i;

    for( i=0;i<=pos;i++ )

        if( !vis[i] )

        {

            if( word[i][0] == str[ str.length()-1 ] && word[i][ word[i].length()-1 ]=='m' ) //满足首尾相连又已'm'结尾

                flag=1;

            else if( word[i][0]==str[ str.length()-1 ] ) //满足首尾相连的情况

            {

                vis[i]=true;

                dfs( word[i] );

                vis[i]=false;

            }

        }

}



int main()

{

    pos=0;

    int i,j;

    memset( vis,false,sizeof(vis) );

    while( cin>>word[pos] )

    {

        if( word[pos][0]=='0' )   //以输入'0'为结尾

        {

            flag=0;

            for( i=0;i<=pos;i++ )

            {

                if( word[i][0]=='b' )

                {

                    vis[i]=true;

                    dfs( word[i] );

                    vis[i]=false;

                }

            }

            if( flag )

                cout<<"Yes.\n";

            else

                cout<<"No.\n";

            pos=0;

            memset( vis,false,sizeof(vis) );  //重新初始化

        }

        else

            pos++; //没有结尾就一直输入下一个

    }

    return 0;

}

 

但当我AC后,稍微一思考,发现可以优化。因为我不需要关注你输入的单词的每一个字母,我所要知道的仅仅为每个输入单词的首字母与末字母。那么我可以建一个链接矩阵,表示两个字母间的链接关系。当然这个连接是单向的,比如输入big,'b'可以指向'g',而不是'g'指向'b'。

 

此处用了BFS:

#include <iostream>

#include <cstring>

#include <string>

#include <queue>

#include <cstdio>



using namespace std;



const int maxn = 30;

bool word[maxn][maxn]; //链接矩阵

bool vis[maxn][maxn];  //是否已访问



bool bfs()

{

    const int start = 'b'-'a';

    const int finish = 'm'-'a';

    queue <int> qt;

    qt.push( start ); //从'b'出发

    int t, i;

    while( !qt.empty() )

    {

        t = qt.front();

        qt.pop();



        if( word[t][finish] )  //找到末尾是'm'的单词

            return true;



        for( i=0;i<='z'-'a';i++ )

            if( !vis[t][i] && word[t][i] )  //寻找未访问的首尾组合

            {

                vis[t][i] = true;

                qt.push(i);

            }

    }

    return false;

}



int main()

{

    string temp;

    memset( vis, false, sizeof(vis) );

    memset( word, false, sizeof(word) );

    while( cin>>temp )

    {

        if( temp[0]=='0' )  //一组输入完毕

        {

            if( bfs() )

                cout<<"Yes.\n";

            else

                cout<<"No.\n";

            memset( vis, false, sizeof(vis) );

            memset( word, false, sizeof(word) );

        }

        else

            word[ temp[0]-'a' ][ temp[ temp.length()-1 ]-'a' ] = true;



    }

    return 0;

}

 

除了BFS,DFS,还可以用最短路径,判断起点'b'能否到'm'即可,这里就不贴代码了。网上也还有很多的其他解法。

总之,这道题不难,但对扩展思路还是有一定帮助的。

你可能感兴趣的:(HDU)