【NOIP2000】单词接龙

本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1019


 

颓废了一段时间,,,现在打算一遍学着数论基础,一遍做着搜索之类的题目提高代码能力。

这道题数据范围小,是一道典型的搜索题,但是对解题能力还是有一定要求的。

注意是解题能力!我认为,他包括这几部分:读题懂题意,化归到算法模型上,编写代码处理好细节。

读懂题是解决题目的前提,有时解题时间长、出错率高不是因为知识掌握少,代码写得乱,就是因为最开始没读懂题就动手。

这道题的话,需要读出以下几点:

1、每个单词最多出现2次。

2、单词有重合部分,且应该是指最小重合部分。

3、存在包含关系的两个单词不能相连。

结合数据范围,我们很容易想到可以用搜索。每次记录已构成的龙最后一个单词以及龙的长度。每次搜索下一个单词,考虑能否接上。

如果不存在可以接上的单词,则用现在累计的长度更新答案;若存在,将其接上,注意累计长度是加上新单词的长度-两单词重叠部分。

代码能力需要做大量的题才能练出来,同样是实现一个功能,代码能力强就可以快速高效地实现,而且不易出错。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string>
 5 using namespace std;
 6 const int maxn=25;
 7 int n,ans,ccnt[maxn][maxn],vis[maxn];
 8 char c;
 9 string s[maxn];
10 inline int con(string a,string b) {
11     int la=a.length(),lb=b.length();
12     for(int cnt=1;cnt<=min(la,lb);++cnt) {
13         int flag=1;
14         for(int i=la-cnt,j=0;j<cnt;++i,++j)
15             if(a[i]!=b[j]) {flag=0;break;}
16         if(flag) return cnt;
17     }
18     return 0;
19 }
20 void dfs(int i,int len) {
21     int flag=1;
22     for(int j=1;j<=n;++j) {
23         if(vis[j]>=2) continue;
24         if(!ccnt[i][j]) continue;
25         if(ccnt[i][j]==(int)s[i].length()||ccnt[i][j]==(int)s[j].length()) continue;
26         flag=0;
27         ++vis[j];
28         dfs(j,len+s[j].length()-ccnt[i][j]);
29         --vis[j];
30     }
31     if(flag&&len>ans) ans=len;
32 }
33 int main() {
34     scanf("%d",&n);
35     for(int i=1;i<=n;++i) cin>>s[i];
36     for(int i=1;i<=n;++i)
37         for(int j=1;j<=n;++j)
38             ccnt[i][j]=con(s[i],s[j]);
39     while((c=getchar())=='\n'||c==' '||c=='\r');
40     for(int i=1;i<=n;++i) if(s[i][0]==c) {
41         ++vis[i];
42         dfs(i,s[i].length());
43         --vis[i];
44     }
45     printf("%d",ans);
46     return 0;
47 }
AC代码

 

转载于:https://www.cnblogs.com/Mr94Kevin/p/9677858.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值