HDOJ1181 字符串首尾相连问题[DFS()+字符串排序strcmp()||▲矩阵标记]

变形课

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 4   Accepted Submission(s) : 1

Font: Times New Roman | Verdana | Georgia

Font Size:

Problem Description

呃......变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个统一规律:如果咒语是以a开头b结尾的一个单词,那么它的作用就恰好是使A物体变成B物体.
Harry已经将他所会的所有咒语都列成了一个表,他想让你帮忙计算一下他是否能完成老师的作业,将一个B(ball)变成一个M(Mouse),你知道,如果他自己不能完成的话,他就只好向Hermione请教,并且被迫听一大堆好好学习的道理.

Input

测试数据有多组。每组有多行,每行一个单词,仅包括小写字母,是Harry所会的所有咒语.数字0表示一组输入结束.

Output

如果Harry可以完成他的作业,就输出"Yes.",否则就输出"No."(不要忽略了句号)

Sample Input

so
soon
river
goes
them
got
moon
begin
big
0

Sample Output

Yes.

Hint

Hint
Harry 可以念这个咒语:"big-got-them".

Source

Gardon-DYGG Contest 1
 
 
code:(TLE)    我知道是自己剪枝没做好,也不知道如果事先不排序的话,是否一定会TLE,希望有人看到,给我指点一下啊!
 
 1 #include<iostream>
 2 using namespace std;
 3 
 4 char data[100][100];                         //数据
 5 int i;                                      //字符串个数
 6 int vst[100];                                //标记是否访问
 7 bool flag;                                  //是否已找到结果
 8 int count;                                 //记录已找到的单词数
 9 
10 void DFS(int tag)
11 {
12     int j;
13     if(count>=i)
14         return;
15     if(data[tag][strlen(data[tag])-1]=='m')                  //出现目标态
16     {
17         flag=true;
18         printf("Yes.\n");
19         return;
20     }
21     for(j=0;j<i;j++)
22     {
23         if(!vst[j]&&data[j][0]==data[tag][strlen(data[tag])-1])    //判断条件:1、未访问过;2、首尾相连
24         {
25             vst[j]=1;
26             count++;
27             DFS(j);
28             if(flag)
29                 return;
30             vst[j]=0;
31         }
32     }
33     return;
34 }
35 
36 int main()
37 {
38     int j;
39     int flag1;               //标记是否有以m结尾的字符串
40     int flag2;               //标记是否有以b开头的字符串
41     while(1)
42     {
43         i=0;
44         flag1=0;
45         flag2=0;
46         flag=false;
47         while(scanf("%s",data[i++]))
48         {
49             if(data[i-1][strlen(data[i-1])-1]=='m')
50                 flag1=1;
51             if(data[i-1][0]=='b')
52                 flag2=1;
53             if((data[i-1][0]-'0')==0)
54                 break;
55         }
56         if(flag1&&flag2)
57         {
58             for(j=0;j<i;j++)
59             {
60                 count=0;
61                 if(data[j][0]=='b')                     //找到以b开头的字符串为根
62                 {
63                     memset(vst,0,sizeof(vst));
64                     vst[j]=1;                           //标记
65                     DFS(j);
66                     if(flag)                            
67                         break;
68                 }
69             }
70         }
71         if(!flag||!flag1||!flag2)
72             printf("No.\n");
73     }
74     return 0;
75 }
 
 别人的代码1:
 
DFS()+字符串排序
      
 1 #include <stdio.h> 
 2 #include <stdlib.h> 
 3 #include <string.h> 
 4 #define N 1000 
 5 #define M 30 
 6 char ch[N][M]; 
 7 int visited[N],n; 
 8   
 9 int cmp(const void *a, const void *b) 
10 { 
11     char *c = (char *) a; 
12     char *d = (char *) b; 
13     return strcmp(c,d); 
14 } 
15   
16 int DFS_Visit(int cur,char *word) 
17 { 
18     int i,flag=0,len=strlen(word); 
19     visited[cur]=1;//对已经选择的单词进行标记 
20     if(word[len-1]=='m') flag=1; 
21     else
22         for(i=0;i<n;i++) 
23         { 
24             if(!visited[i]&&word[len-1]==ch[i][0])//搜索前提 
25                 if(DFS_Visit(i,ch[i])) 
26                 { 
27                     flag=1; 
28                 } 
29         } 
30     visited[cur]=0;//标记还原,以便上一层的搜索可以继续选择该单词 
31     return flag; 
32 } 
33   
34 int DFS() 
35 { 
36     int i; 
37     memset(visited,0,sizeof(visited)); 
38     qsort(ch,n,sizeof(ch[0]),cmp);//按字典序排列 
39     for(i=0;i<n;i++)//递归外层枚举以b为首的字母 
40     { 
41         if(ch[i][0]>'b') break;//首字母比b大的都不用搜索 
42         if(ch[i][0]=='b') 
43             if(DFS_Visit(i,ch[i])) 
44                 return 1; 
45     } 
46     return 0; 
47 } 
48   
49 int main() 
50 { 
51     int i=0; 
52 //  freopen("变形课.txt","r",stdin); 
53     while(gets(ch[i])!=NULL) 
54     { 
55         if(ch[i][0]=='0') 
56         { 
57             n=i,i=-1; 
58             if(DFS()) printf("Yes.\n"); 
59             else printf("No.\n"); 
60         } 
61         i++; 
62     } 
63     return 0; 
64 }

 别人的代码2:(▲矩阵标记)                       

                      不错的思维方式!

                      虽然这代码过了测试数据,其实是不正确的

                      例如测试数据为:

                      另外说一句,杭电里的这道题测试数据是有缺陷的,如果你第一次输出的是Yes.,之后全部输出No.也能过了。

                    

                                         

 1 #include<iostream>
 2 using namespace std;
 3 int main()
 4 {
 5     int i,j,k,len;
 6     char s[100],mark[30][30];             //s存数据,mark标记
 7     while(gets(s))
 8     {
 9         memset(mark,0,sizeof(mark));
10         while(s[0]!='0')
11         {
12             len=strlen(s);
13             mark[s[0]-'a'][s[len-1]-'a']=1;
14             gets(s);
15         }
16         for(k=0;k<26;k++)
17             for(i=0;i<26;i++)
18             {
19                 if(i!=k&&mark[k][i]==1)
20                 {
21                     for(j=0;j<26;j++)
22                         if(mark[k][j]||mark[i][j])
23                             mark[k][j]=1;
24                 }
25             }
26         if(mark[1][12]==1)
27             puts("Yes.");
28         else
29             puts("No.");
30     }
31     return 0;
32 }

 别人的代码3:

      很标准的代码,我的目标!

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <string>
 5 #include <algorithm>
 6 #include <iostream>
 7 using namespace std;
 8 const int N=110;
 9 
10 string str[N];
11 bool vis[N],flag;
12 int cnt;
13 
14 void dfs(char s)
15 {
16     if(s=='m')
17     {
18         flag=true; 
19         return ;
20     }
21     for(int i=0;i<cnt;i++)
22     {
23         if(str[i][0]==s&&!vis[i])
24         {
25             int len=str[i].length();
26             vis[i]=true;
27             dfs(str[i][len-1]);
28             vis[i]=false;
29         }
30     }
31 }
32 
33 int main(){
34     
35     // freopen("data.in","r",stdin);
36     // freopen("data.out","w",stdout);
37     
38     while(cin>>str[cnt])
39     { 
40         if(str[cnt]=="0")
41         {
42             memset(vis,false,sizeof(vis));
43             flag=false;
44             dfs('b');
45             if(flag) puts("Yes.");
46             else puts("No.");
47             cnt=0; 
48         } 
49         cnt++; 
50     }
51     return 0;
52 }

 
 
补充:
    

(一)strcmp函数  

         strcmp函数是比较两个字符串的大小,返回比较的结果。一般形式是:  

                 i=strcmp(字符串,字符串);

         其中,字符串1、字符串2均可为字符串常量或变量;i   是用于存放比较结果的整型变量。比较结果是这样规定的:  

        ①字符串1小于字符串2,strcmp函数返回一个负值;

        ②字符串1等于字符串2,strcmp函数返回零;

        ③字符串1大于字符串2,strcmp函数返回一个正值;那么,字符中的大小是如何比较的呢?来看一个例子。

         实际上,字符串的比较是比较字符串中各对字符的ASCII码。首先比较两个串的第一个字符,若不相等,则停止比较并得出大于或小于的结果;如果相等就接着 比较第二个字符然后第三个字符等等。如果两上字符串前面的字符一直相等,像"disk"和"disks"   那样,   前四个字符都一样,   然后比较第 五个字符,   前一个字符串"disk"只剩下结束符'/0',后一个字符串"disks"剩下's','/0'的ASCII码小于's'的ASCII 码,所以得出了结果。因此无论两个字符串是什么样,strcmp函数最多比较到其中一个字符串遇到结束符'/0'为止,就能得出结果。

注意:字符串是数组类型而非简单类型,不能用关系运算进行大小比较。  

         if("ABC">"DEF")   /*错误的字符串比较*/

         if(strcmp("ABC","DEF")   /*正确的字符串比较*/

(二)strcpy函数  

         strcpy函数用于实现两个字符串的拷贝。一般形式是:  

                 strcpy(字符中1,字符串2)

         其中,字符串1必须是字符串变量,而不能是字符串常量。strcpy函数把字符串2的内容完全复制到字符串1中,而不管字符串1中原先存放的是什么。复制后,字符串2保持不变。  

例:    

         注意,由于字符串是数组类型,所以两个字符串复制不通过赋值运算进行。  

         t=s;   /*错误的字符串复制*/

         strcpy(t,s);   /*正确的字符串复制*/


心得:

     //    写代码要简洁,高效
     //    先对字符串数组进行排序
     //    strcmp()
     //    当题目做不出来时就给自己的代码写备注







            If you have any questions about this article, welcome to leave a message on the message board.



Brad(Bowen) Xu
E-Mail : maxxbw1992@gmail.com


原文地址:https://www.cnblogs.com/XBWer/p/2555719.html