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:
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行代码满满的是泪。。。





原文地址:https://www.cnblogs.com/bobble/p/5929503.html