• Luogu P1278 单词游戏(dfs)


    P1278 单词游戏

    题意

    题目描述

    (Io)(Ao)在玩一个单词游戏。

    他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致。

    游戏可以从任何一个单词开始。

    任何单词禁止说两遍,游戏中只能使用给定词典中含有的单词。

    游戏的复杂度定义为游戏中所使用的单词长度总和。

    编写程序,求出使用一本给定的词典来玩这个游戏所能达到的游戏最大可能复杂度。

    输入输出格式

    输入格式:

    输入文件的第一行,表示一个自然数(N(1 leq N leq 16))(N)表示一本字典中包含的单词数量以下的每一行包含字典中的一个单词,每一个单词是由字母(A)(E)(I)(O)(U)组成的一个字符串,每个单词的长度将小于等于(100),所有的单词是不一样的。

    输出格式:

    输出文件仅有一行,表示该游戏的最大可能复杂度。

    输入输出样例

    输入样例:

    5
    IOO
    IUUO
    AI
    OIOOI
    AOOI
    

    输出样例:

    16
    

    思路

    骗分过样例,暴力出奇迹! --sbw

    骗分用爆搜过了一道记忆化搜索题,有点开心。

    这题的爆搜其实十分好写,而(n)又很小,不过细细想来,如果每次(dfs)时全部跑满,时间复杂度是(O(n!))的,那么对于最大的数据范围:

    [16!=20922789888000=TLE ]

    显然就会爆炸。那么想想,出题人会怎么卡你呢?首先,他可以做一个环:

    IOI
    IOOI
    IOOOI
    IOOOOI
    IOOOOOI
    ...
    

    这样的话每种情况都能转移到,就会把爆搜的时间复杂度跑满。针对这样的出题人,我们只需要记录所有字符串的长度和(也就是最大可能答案),一旦搜到就赶紧退出,就不会(TLE)了。

    狡猾的出题人也想到了这一点,于是造出了这样的数据:

    UE
    IOI
    IOOI
    IOOOI
    IOOOOI
    IOOOOOI
    ...
    

    不过这也好办,我们在总长度中减去永远不会遍历到的字符串来更新就好了。

    于是这题就被这么水了过去...

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,ans,sum,len[20];
    string str[20];
    bool vis[20],ok[20];
    vector<int>G[20];
    void dfs(int now,int step)
    {
        if(ans==sum) return ;
        ans=max(ans,step);
        for(int i=0;i<G[now].size();i++)
            if(!vis[G[now][i]])
            {
                vis[G[now][i]]=true;
                dfs(G[now][i],step+len[G[now][i]]);
                vis[G[now][i]]=false;
            }
    }
    int main()
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>str[i];
            sum+=(len[i]=str[i].length());
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(i!=j&&str[i][len[i]-1]==str[j][0])
                {
                    ok[i]=ok[j]=true;
                    G[i].push_back(j);
                }
        for(int i=0;i<n;i++) if(!ok[i]) sum-=len[i];
        for(int i=0;i<n;i++)
        {
            if(!ok[i]) continue;
            vis[i]=true;
            dfs(i,len[i]);
            vis[i]=false;
            if(ans==sum) break;
        }
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    视频会议保险行业解决方案
    如何选择适合企业的音视频解决方案?
    移动视频会议市场
    网络视频通讯服务器和平台发展
    移动互联网化的远程医疗
    智能家居行业的音视频技术
    Ubuntu15.04 安装Android开发环境
    AspNetPager 自定义html
    SqlDataReader对象的NextResult方法读取存储过程多个结果集
    一些原生云APP
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9759877.html
Copyright © 2020-2023  润新知