首页 > 其他分享 >洛谷题单指南-搜索-P1019 [NOIP2000 提高组] 单词接龙

洛谷题单指南-搜索-P1019 [NOIP2000 提高组] 单词接龙

时间:2024-03-07 14:58:42浏览次数:24  
标签:NOIP2000 int 洛谷题 公共 单词 flag 接龙 长度 P1019

原题链接:https://www.luogu.com.cn/problem/P1019

题意解读:要计算接龙能得到的最长字符串,可以通过DFS暴搜所有可能的接龙方案

解题思路:

DFS的关键在于两个判断:

1、下一个单词是否可以和上一个单词接龙,最短公共长度是多少(只需要看两个单词的最短公共长度,这样能保证接龙更长)

2、单词是否已接龙两次

判断2通过int flag[N]即可解决,下面重点讨论判断1如何处理

设int conn[i][j]表示在第i个单词后接第j个单词时,最少的公共长度,如果为0说明不能接

通过双重循环枚举所有单词,可以得到两两之间的最少公共长度

具体说来:

只需要针对两个单词s1、s2,从1开始枚举公共长度k(不能超过任意字符串的长度,因为不能存在包含关系)

判断s1的后k位是否和s2的前k位相同,找到则保存最小的k,详细过程请参考代码。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 25;

int conn[N][N]; //conn[i][j]表示第i个单词后接第j个单词时,最少的公共长度,如果为0说明不能接
string s[N]; //所有单词
int flag[N]; //每个单词被用了多少次
int n;
char first;
int ans;

//str:接龙 idx:上一个接上的单词
void dfs(string str, int idx)
{
    ans = max(ans, (int)str.length());
    
    for(int i = 1; i <= n; i++)
    {
        if(conn[idx][i] > 0 && flag[i] < 2) //如果存在可接龙的单词
        {
            string longstr = str; //接龙后的字符串
            for(int j = conn[idx][i]; j < s[i].length(); j++)
            {
                longstr += s[i][j]; //接龙操作
            }
            flag[i]++;
            dfs(longstr, i); //继续找下一个可接龙的单词
            flag[i]--;
        }
    }
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> s[i];
    cin >> first;

    //计算每两个单词相接的最短公共长度,由于不能存在包含关系,公共长度要小于长度较小的字符串
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            for(int k = 1; k < min(s[i].length(), s[j].length()); k++) //枚举公共长度可能的值
            {
               
                bool isk = true; //公共长度是否是k
                string s1 = s[i]; int start1 = s1.length() - k;
                string s2 = s[j]; int start2 = 0;
                
                for(int l = 1; l <= k; l++)
                {
                    if(s1[start1] != s2[start2])
                    {
                        isk = false;
                        break;
                    }
                    start1++; start2++;
                }

                if(isk)
                {
                    conn[i][j] = k;
                    break; //找到最短的公共长度,就应该结束,这样才能保证接上的龙最长
                } 
            }
        }
    }

    for(int i = 1; i <= n; i++)
    {
        if(s[i][0] == first) 
        {
            memset(flag, 0, sizeof(flag)); //从每一个可能的单词开始dfs,都需要重置flag
            flag[i]++;
            dfs(s[i], i);
        }
    }

    cout << ans;

    return 0;
}

 

标签:NOIP2000,int,洛谷题,公共,单词,flag,接龙,长度,P1019
From: https://www.cnblogs.com/jcwy/p/18058870

相关文章

  • 洛谷题单指南-搜索-P1605 迷宫
    原题链接:https://www.luogu.com.cn/problem/P1605题意解读:从起点走到终点的方案数,DFS可遍历所有情况。解题思路:在DFS过程中,有两种标记墙:不能访问已访问过的,不能重复访问定义数组inta[N][N]表示迷宫,1是墙或者已访问过的,0是可以通过的。100分代码:#include<bits/stdc++.h>......
  • 洛谷题单指南-搜索-P1433 吃奶酪
    原题链接:https://www.luogu.com.cn/problem/P1433题意解读:计算经过所有奶酪一次的总路径最短,可以采用dfs、dp等方法。解题思路:最直接的思路是DFS,暴搜所有的路径方案,计算最小距离,n最大是15,复杂度为15!≈10^12,必定会超时,先保证正确性,得到部分分:50分代码:#include<bits/stdc++.h......
  • 洛谷题单指南-搜索-P2895 [USACO08FEB] Meteor Shower S
    原题链接:https://www.luogu.com.cn/problem/P2895题意解读:所谓安全格子,就是在所有流星坠落之后,没有被烧焦的格子,要计算从起点到这些格子任一一个的最短路径,BFS可以解决。解题思路:1、读取数据,先把所有流星坠落点以及周围被烧焦的格子进行标记,得到安全格子2、从起点开始BFS,每走......
  • 洛谷题单指南-搜索-P1135 奇怪的电梯
    原题链接:https://www.luogu.com.cn/problem/P1135题意解读:计算A到B至少要按几次电梯,本质上就是求A到B的最短路径,可以通过BFS解决。解题思路:位于每一层,有两种选择:向上、向下BFS搜索直接从A找到B,每扩展一层,层数+1,层数即按电梯次数100分代码:#include<bits/stdc++.h>usingnam......
  • 洛谷题单指南-搜索-P1443 马的遍历
    原题链接:https://www.luogu.com.cn/problem/P1443题意解读:无论是国际象棋还是中国象棋,马的活动范围都是一样的:只不过国际象棋棋子是在格子中,中国象棋棋子是在交点,坐标的变化方式是一样的,根据此活动范围,计算马到达每一个点的最短路径。解题思路:根据马的活动范围,在棋盘内进行B......
  • 洛谷题单指南-搜索-P2392 kkksc03考前临时抱佛脚
    原题链接:https://www.luogu.com.cn/problem/P2392解题思路:参考https://www.cnblogs.com/jcwy/p/18003097前面已经给出了二进制法的代码,这里给出DFS的代码100分代码:#include<bits/stdc++.h>usingnamespacestd;constintN=25;ints1,s2,s3,s4;inta[N],b[N],c[......
  • 洛谷题单指南-搜索-P1219 [USACO1.5] 八皇后 Checker Challenge
    原题链接:https://www.luogu.com.cn/problem/P1219题意解读:八皇后,经典回溯问题。解题思路:逐行摆放棋子,关键在于如何快速判断行、列、正斜(左上到右下)、反斜(右上到左下)方向没有已放其他棋子1、由于逐行摆放,因此行不需要判断通过一个boolcol[N]数组即可判断列上是否已摆放其他棋......
  • 洛谷题单指南-二分查找与二分答案-P3743 kotori的设备
    原题链接:https://www.luogu.com.cn/problem/P3743题意解读:设备使用的时间越久,需要充电的总时间也越多,具备单调性,根据使用的时间,计算需要充电的时间,如果充电总时间<=使用的时间,说明有电量还能富余,使用时间还可以更多,因此只需对使用时间进行二分即可。解题思路:给定设备使用的时间......
  • 洛谷题单指南-二分查找与二分答案-P1163 银行贷款
    原题链接:https://www.luogu.com.cn/problem/P1163题意解读:利率越小,贷款期限和每个月还的钱固定的情况下,越有可能能够还完全部的贷款,具备单调性,因此给定贷款利率、贷款月数、每月还款钱数,可以计算最终贷款还剩下多少,有两种情况:>=0,说明利率可能大了,要试探更小利率;<0,说明利率小了,要......
  • 洛谷题单指南-二分查找与二分答案-P1182 数列分段 Section II
    原题链接:https://www.luogu.com.cn/problem/P1182题意解读:每段和的最大值越小,则分段数就越多,因此可以通过给定每段和的最大值,将分段数划分为两类:<=M,>M,对每段和的最大值进行二分即可。解题思路:二分的判定条件为,给定每段和的最大值,计算分段数,计算逻辑如下:依次遍历每一个数,求当前......