【单词方阵】
声明
我的码风可能有点和别人不太一样(其实就是有点奇怪),大家重在意会即可。
注:此为原洛谷博客的博文
目录
这个目录就是用来凑字数的,呵呵哒
原题转载
前言
60分骗分代码详解
100分AC代码详解
后记
原题转载
题目描述
给一个n×n的字母方阵,内可能蕴含多个“yizhong
”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*
代替,以突出显示单词。例如:
输入:
8 输出:
qyizhong *yizhong
gydthkjy gy******
nwidghji n*i*****
orbzsfgz o**z****
hhgrhwth h***h***
zzzzzozo z****o**
iwdfrgng i*****n*
yyyygggg y******g
输入输出格式
输入格式:
第一行输入一个数nn。(7 \le n \le 1007≤n≤100)。
第二行开始输入n \times nn×n的字母矩阵。
输出格式:
突出显示单词的n \times nn×n矩阵。
前言
作为一道被卡了1个小时才做出这道水题萌新,表示自己码风有点菜,于是决定多做一点解释,毕竟80行的代码可能确实有点水QAQ。
60分骗分代码详解
首先,为了便于比对单词,我建立了一个string类对象存储题目要求的单词(我表示并不清楚这个单词是否有实际意义,如果有哪位大佬知道,欢迎在评论里告诉我)
string ans=" yizhong";
然后,n与m表示数组下标,用no表示该下标所应该对应的字母的编号,如:
int dfs(int n,int m,int no)
如果越界:
if(n<1||m<1||n>num||m>num) return 0;
上深搜伪代码(解释以注释形式出现在代码中):
1 int dfs(int n,int m,int no) 2 { 3 if(n<1||m<1||n>num||m>num)//如果越界则返回 4 return 0; 5 if(a[n][m]==ans[no])//如果是对应字母,则继续深搜 6 { 7 if(no==7)//如果搜到最后一个,则返回1,表示深搜成功 8 { 9 book[n][m]=1; 10 return 1; 11 } 12 else 13 { 14 //搜索每一种可能 15 if(dfs(n+1,m,no+1)||dfs(n,m-1,no+1)||dfs(n,m+1,no+1)||dfs(n-1,m,no+1)||dfs(n+1,m-1,no+1)||dfs(n+1,m+1,no+1)||dfs(n-1,m-1,no+1)||dfs(n-1,m+1,no+1)) 16 { 17 //若搜索成功,标记该字符是单词的一部分 18 book[n][m]=1; 19 return 1; 20 } 21 else 22 return 0; 23 } 24 } 25 else//否则返回0 26 return 0; 27 }
大家仔细观察便会发现该代码的漏洞:他搜索所有的方向,因此如果有弯曲的字符连在一起与要求单词相同,它便认为该字符是单词的一部分,然而,题目要求必须是横或竖或斜直着相连的字符串才参与比对,故若有该类型的数据,此代码就会出错(这便是他只能作为骗分代码的原因)
最后,上你们最爱的完整代码(第一个和第三个点会WA,原因上面已经解释过,因此只能得60分)
1 #include<iostream> 2 #include <string> 3 using namespace std; 4 5 char a[102][102]; 6 bool book[102][102]={0};//标记对应字符是否是要求单词的一部分 7 int num; 8 9 int dfs(int n,int m,int no) 10 { 11 if(n<1||m<1||n>num||m>num)//如果越界则返回 12 return 0; 13 if(a[n][m]==ans[no])//如果是对应字母,则继续深搜 14 { 15 if(no==7)//如果搜到最后一个,则返回1,表示深搜成功 16 { 17 book[n][m]=1; 18 return 1; 19 } 20 else 21 { 22 //搜索每一种可能 23 if(dfs(n+1,m,no+1)||dfs(n,m-1,no+1)||dfs(n,m+1,no+1)||dfs(n-1,m,no+1)||dfs(n+1,m-1,no+1)||dfs(n+1,m+1,no+1)||dfs(n-1,m-1,no+1)||dfs(n-1,m+1,no+1)) 24 { 25 //若搜索成功,标记该字符是单词的一部分 26 book[n][m]=1; 27 return 1; 28 } 29 else 30 return 0; 31 } 32 } 33 else//否则返回0 34 return 0; 35 } 36 int main() 37 { 38 //读入 39 cin>>num; 40 for(int i=1;i<=num;i++) 41 for(int j=1;j<=num;j++) 42 { 43 cin>>a[i][j]; 44 } 45 //深搜 46 for(int i=1;i<=num;i++) 47 for(int j=1;j<=num;j++) 48 dfs(i,j,1); 49 //输出 50 for(int i=1;i<=num;i++) 51 { 52 for(int j=1;j<=num;j++) 53 { 54 if(book[i][j]) 55 cout<<a[i][j]; 56 else 57 cout<<"*"; 58 } 59 cout<<endl; 60 } 61 return 0; 62 }
100分AC代码详解
我们说,上面的代码只能得60分的原因在于他不判断方向,而深搜所有的方向,因此会出错,解决代码也十分简单:在dfs()函数中加一个表示方向的参数f即可:
1 int dfs(int n,int m,int no,int f) 2 { 3 if(n<1||m<1||n>num||m>num)//如果越界则返回 4 return 0; 5 if(a[n][m]==ans[no])//如果是对应字母,则继续深搜 6 { 7 if(no==7)//如果搜到最后一个,则返回1,表示深搜成功 8 { 9 book[n][m]=1; 10 return 1; 11 } 12 else 13 { 14 //有选择性的搜索 15 switch (f) 16 { 17 case 1: if(dfs(n-1,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 18 case 2: if(dfs(n-1,m,no+1,f)){book[n][m]=1;return 1;}else return 0; 19 case 3: if(dfs(n-1,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 20 case 4: if(dfs(n,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 21 /*case 5表示no==1, 22 作为第一个字母,因此是个特例,要向所有方向搜索 23 其余情况都只向一个特定方向搜索*/ 24 case 5: 25 if(dfs(n-1,m-1,no+1,1)) 26 book[n][m]=1; 27 if(dfs(n-1,m,no+1,2)) 28 book[n][m]=1; 29 if(dfs(n-1,m+1,no+1,3)) 30 book[n][m]=1; 31 if(dfs(n,m-1,no+1,4)) 32 book[n][m]=1; 33 if(dfs(n,m+1,no+1,6)) 34 book[n][m]=1; 35 if(dfs(n+1,m-1,no+1,7)) 36 book[n][m]=1; 37 if(dfs(n+1,m,no+1,8)) 38 book[n][m]=1; 39 if(dfs(n+1,m+1,no+1,9)) 40 book[n][m]=1; 41 break; 42 case 6: if(dfs(n,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 43 case 7: if(dfs(n+1,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 44 case 8: if(dfs(n+1,m,no+1,f)){book[n][m]=1;return 1;}else return 0; 45 case 9: if(dfs(n+1,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 46 } 47 48 } 49 } 50 else//如果搜到最后一个,则返回1,表示深搜成功 51 return 0; 52 }
你们最爱的100分AC完整代码:
1 #include<iostream> 2 #include <string> 3 using namespace std; 4 5 string ans=" yizhong"; 6 char a[102][102]; 7 bool book[102][102]={0}; 8 int num; 9 int dfs(int n,int m,int no,int f); 10 11 int main() 12 { 13 freopen("cs.in","r",stdin); 14 cin>>num; 15 for(int i=1;i<=num;i++) 16 for(int j=1;j<=num;j++) 17 cin>>a[i][j]; 18 for(int i=1;i<=num;i++) 19 for(int j=1;j<=num;j++) 20 dfs(i,j,1,5); 21 for(int i=1;i<=num;i++) 22 { 23 for(int j=1;j<=num;j++) 24 { 25 if(book[i][j]) 26 cout<<a[i][j]; 27 else 28 cout<<"*"; 29 } 30 cout<<endl; 31 } 32 return 0; 33 } 34 35 int dfs(int n,int m,int no,int f) 36 { 37 if(n<1||m<1||n>num||m>num)//如果越界则返回 38 return 0; 39 if(a[n][m]==ans[no])//如果是对应字母,则继续深搜 40 { 41 if(no==7)//如果搜到最后一个,则返回1,表示深搜成功 42 { 43 book[n][m]=1; 44 return 1; 45 } 46 else 47 { 48 //有选择性的搜索 49 switch (f) 50 { 51 case 1: if(dfs(n-1,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 52 case 2: if(dfs(n-1,m,no+1,f)){book[n][m]=1;return 1;}else return 0; 53 case 3: if(dfs(n-1,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 54 case 4: if(dfs(n,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 55 /*case 5表示no==1, 56 作为第一个字母,因此是个特例,要向所有方向搜索 57 其余情况都只向一个特定方向搜索*/ 58 case 5: 59 if(dfs(n-1,m-1,no+1,1)) 60 book[n][m]=1; 61 if(dfs(n-1,m,no+1,2)) 62 book[n][m]=1; 63 if(dfs(n-1,m+1,no+1,3)) 64 book[n][m]=1; 65 if(dfs(n,m-1,no+1,4)) 66 book[n][m]=1; 67 if(dfs(n,m+1,no+1,6)) 68 book[n][m]=1; 69 if(dfs(n+1,m-1,no+1,7)) 70 book[n][m]=1; 71 if(dfs(n+1,m,no+1,8)) 72 book[n][m]=1; 73 if(dfs(n+1,m+1,no+1,9)) 74 book[n][m]=1; 75 break; 76 case 6: if(dfs(n,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 77 case 7: if(dfs(n+1,m-1,no+1,f)){book[n][m]=1;return 1;}else return 0; 78 case 8: if(dfs(n+1,m,no+1,f)){book[n][m]=1;return 1;}else return 0; 79 case 9: if(dfs(n+1,m+1,no+1,f)){book[n][m]=1;return 1;}else return 0; 80 } 81 82 } 83 } 84 else//如果搜到最后一个,则返回1,表示深搜成功 85 return 0; 86 }
后记
相信大家看到这里,便会感到深搜原来就是这么简单!记住:代码长!=晦涩难懂!无需十分在意自己的码风,能AC的代码就是好代码!最后,我辛苦敲了这么多,各位大佬能否给个赞呢?~~~