//题目-----------------------------------------------------------------------------------------
传送门: http://www.luogu.org/problem/show?pid=1101
P1101 单词方阵
题目描述
给一nXn的字母方阵,内可能蕴含多个“yizhong”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间[color=red]可以[/color]交叉,因此有可能共用字母。输出时,将不是单词的字母用“*”代替,以突出显示单词。例如:
输入:
8 输出:
qyizhong *yizhong
gydthkjy gy******
nwidghji n*i*****
orbzsfgz o**z****
hhgrhwth h***h***
zzzzzozo z****o**
iwdfrgng i*****n*
yyyygggg y******g
输入输出格式
输入格式:
第一行输入一个数n。(7<=n<=100)。
第二行开始输入nXn的字母矩阵。
输出格式:
突出显示单词的nXn矩阵。
输入输出样例
输入样例#1:
7 aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa
输出样例#1:
******* ******* ******* ******* ******* ******* ******* //解题--------------------------------------------------------------------------------
【题解区似乎没人用这方法,虽然不是最优。。不过憋了一个多小时没看题解,苦苦debug后终于AC的这感觉。。。
首先在看到这东西时,根本不觉得是DFS【QAQ】,后来想尽方法把它和DFS扯上关系,终于得出了一个奇葩的方法:
. 因为yizhong里每个字母都是独一无二的,所以
. 可以将他们与1,2,3,4,5,6,7一一对应,
. 即: 1---y, 2---i, 3---z, 4---h, 5---o, 6---n, 7---g
//注:以下说到的层,是指搜索树的每一层【就是DFS里面的深度】
1. 以每行一个string的形式读入数据并转存该方阵到二维布尔数组,
. 将每一个在‘yizhong’里面的字母的坐标分别存在rx和ry,count[i]为该字母的个数;
2. 一层层try,找每一层即找‘yizhong’里的每一个字母(第一层找y,第二层找i,第三层找z……)
. 怎么找呢? 这时就要用的rx和ry啦 如果对应的坐标能够通过检查,就找下一层(当深度小于7时)
. 关于这里的检查: 用到一个过程checkfirst和一个函数check,
. 因为如果找到yi,那么就大致确定了这个yizhong的方向,checkfirst就是这个功能而且顺带判断可不可用
. check呢,就是判断这个字母是不是在和前面的在同一直线,且相邻
. 这样找的话,
. 如果能找到第七层(yizhong长7)就说明找到了一个‘yizhong’,
. 此时就调用chuli过程进行处理(即把ju数组里面的相应位置标记用于输出时判断)
3. 输出时,如果ju数组中的元素为false【说明是yizhong的一部分】就输出它本身,否则输出*
//代码---------------------------------------------------------------------------------
program dancifangzhen; //----------------------------------------------------------------- const // 1---y, 2---i, 3---z, 4---h, 5---o, 6---n, 7---g bian:array[‘g‘..‘z‘] of integer=(7,4,2,0,0,0,0,6,5,0,0,0,0,0,0,0,0,0,1,3); //----------------------------------------------------------------- var n,i,j,lx,ly,pull:longint; t:char; count:array[1..7] of integer; rx,ry:array[1..7,1..10000] of integer; ju:array[1..100,1..100] of boolean; ans:array[1..7,1..2] of integer; inin:set of char; inp:array[1..100,1..100] of char; st:string; //----------------------------------------------------------------- procedure chuli; var z:longint; begin for z:=1 to 7 do ju[ans[z,1],ans[z,2]]:=false; //对应的标记为false end; //----------------------------------------------------------------- procedure checkfirst(a,b:longint); begin pull:=0; if (a-lx<-1) or (a-lx>1) then exit; //不在其上一行,下一行或同一行 if (b-ly<-1) or (b-ly>1) then exit; //不在其左一列,有一列或同一列 if (lx=a) then pull:=1;//1表示在同一行 if (ly=b) then pull:=2;//2表示在同一列 if (lx+ly=a+b) then pull:=3;//3表示在同一 ‘/’ 斜线 if (ly-lx=b-a) then pull:=4;//4表示在同一 ‘\ ’斜线 end; //----------------------------------------------------------------- function check(a,b:longint):boolean; begin if (a-lx<-1) or (a-lx>1) then exit(false); //不在其上一行,下一行或同一行 if (b-ly<-1) or (b-ly>1) then exit(false); //不在其左一列,有一列或同一列 if pull=1 then if a<>lx then exit(false);//1----行 if pull=2 then if b<>ly then exit(false);//2----列 if pull=3 then if lx+ly<>a+b then exit(false);//3---- ‘/’ 斜线 if pull=4 then if ly-lx<>b-a then exit(false);//4---- ‘\’ 斜线 exit(true); end; //----------------------------------------------------------------- procedure try(d:longint); var i,x,y:longint; begin for i:= 1 to count[d] do begin x:=rx[d,i]; y:=ry[d,i]; if d<>1 then begin //第一个没有前一个字母 lx:=ans[d-1,1]; ly:=ans[d-1,2]; //记录前一个字母 end; if d=2 then begin checkfirst(x,y);//第二次才开始要判断 if pull=0 then continue; //pull等于0时表示它不在上一个的任意一条对角线或横纵线上 end; if (d>2) and (check(x,y)=false) then continue; //没通过检查 ans[d,1]:=x; ans[d,2]:=y; //记录 if d<7 then try(d+1) //还没找完一个继续try else chuli; //找完一个就处理 end; end; //----------------------------------------------------------------- begin inin:=[‘y‘,‘i‘,‘z‘,‘h‘,‘o‘,‘n‘,‘g‘]; //‘yizhong’集合 fillchar(ju,sizeof(ju),true); readln(n); for i:= 1 to n do begin readln(st); //字符串读入比较好,字符很容易出错 for j:= 1 to length(st) do begin inp[i,j]:=st[j]; t:=st[j]; if t in inin then begin inc(count[bian[t]]); rx[bian[t],count[bian[t]]]:=i; ry[bian[t],count[bian[t]]]:=j; end; end; end; try(1); for i:= 1 to n do begin for j:= 1 to n do //输出过程 if ju[i,j] then write(‘*‘) else write(inp[i,j]); writeln; end; end.
//99行代码满满的是泪。。。