HDOJ-1181 字符串首尾相连问题[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已经将他所会的所有咒语都列成了一个表,他想让你帮忙计算一下他是否能完成老师的作业,将一个B(ball)变成一个M(Mouse),你知道,如果他自己不能完成的话,他就只好向Hermione请教,并且被迫听一大堆好好学习的道理.
Input
Output
Sample Input
so soon river goes them got moon begin big 0
Sample Output
Yes.
Hint
Harry 可以念这个咒语:"big-got-them".
Source
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 #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