首页 > 代码库 > P1101 单词方阵【洛谷】

P1101 单词方阵【洛谷】

//题目-----------------------------------------------------------------------------------------

传送门: 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:
7aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
输出样例#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;          //对应的标记为falseend;//-----------------------------------------------------------------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行代码满满的是泪。。。





P1101 单词方阵【洛谷】