1. 程式人生 > >Boggle (UVALive 7299) Regionals 2015--North America - South Central USA

Boggle (UVALive 7299) Regionals 2015--North America - South Central USA

                                                                               Boggle

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=716&page=show_problem&problem=5311
Boggle is a game in which 16 dice with letters on each side are placed into a 4 × 4 grid. Players then
attempt to find words using letters from adjacent dice. You must write a program to find words from
letters in a Boggle-like grid.
When forming a word, each letter must be adjacent in the grid (horizontally, vertically, or diagonally)
to the previous letter, and each grid position (not necessarily each letter) may only appear once in each
word.
In normal Boggle, every side of each die contains a single letter with one exception. No side has the
letter q by itself; instead, the 2 letters qu appear together. Similarly, when the letter q appears in one
of the grids in this problem’s Boggle variant, it should be treated as qu.
Input
Input consists of a dictionary of words followed by several letter grids.
The first line contains an integer W (1 ≤ W ≤ 200) indicating the number of words in the dictionary.
Each of the following W lines contains a string of 1 to 25 lowercase ASCII letters (a - z) representing
a unique word in the dictionary.
The dictionary is followed by 1 or more letter grids. Each begins with a line containing an integer
D (2 ≤ D ≤ 8) indicating the size of that grid (square of size D × D) or 0 (zero) indicating end of
input. The following D lines each contain D lowercase ASCII letters (a - z); each line represents a row
in the grid.
Output
For each grid, output consists of the following:
• A line for each dictionary word that was found in the grid, sorted alphabetically.
• A line containing a dash (-).


Sample Input
3
april
purple
quilt
5
rprit
ahqln
ietep
zrysg
ogwey
3
pel
aup
bcr
0

Sample Output
april
quilt
-
purple
-

思路: 深搜,對字典中每個單詞在網格中進行搜尋,找到的話就輸出(要排序,從小到大按字典序),然後比賽的時候掉了好多坑。

1. 首先,DFS函式最後一行的  vis[x][y]我們沒加,之所以要加這一行,是因為當你搜一條路發現搜錯了,這條路不能滿足整個單詞,然後就要回溯吧,回溯到可以繼續搜的地方(假設一定可以搜出來),但是搜過得錯的那條路上的點你都已經標記了,所以如果正確的路上如果包含你已經標記過得點了,你就不可以搜這個點了,然後本來可以搜出來的單詞就搜不出來了。

舉個例子吧:假設有一個單詞是  abwcdw   ,然後網格是 

abwx
bxcx
wdxx
xxxx

如果你剛開始是從a到a下面的b時,搜到w的時候你會發現走不動了,然後你會回溯到a繼續搜a左面的b,然後搜到最後那個w的時候,發現那個w已經被你剛才的錯誤的搜尋加上標記了,所以。。。

2. 關於q的問題,剛開始我們也理解錯了,應該是當網格中出現q的時候,要把q當成qu,即一個單詞中的q後面必須是u,否則這個單詞不會在網格中搜到。

3. 然後最後還T了一發,flag陣列就是減少一些搜尋的

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cstring>
#include<set>
using namespace std;
typedef long long LL ;
string s[2100];
char dfs[100][100];
int vis[100][100];
int f[8][2]={{1,0},{-1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};
set<string> ans;
int n,m;
bool flag[1000];
void init()
{
    cin>>m;
    for(int i=0;i<m;i++)
        cin>>s[i];
    return ;
}
void DFS(int x,int y,int k,int res)
{
    vis[x][y]=1;
    if(flag[k]==1)  //降低時間複雜度,沒加的時候T了
        return ;
    if(dfs[x][y]=='q')  //把q當成qu,即q後面必須是u,否則這個單詞不會在網格中搜到
    {
        if(s[k][res+1]=='u'&&res+1<s[k].size())
            res++;
        else
            return ;
    }
    if(res==s[k].size()-1)
    {
        ans.insert(s[k]);
        flag[k]=1;
        return ;
    }
    for(int i=0;i<8;i++)
    {
        int z=x+f[i][0],o=y+f[i][1];
        if(z>=0&&z<n&&o>=0&&o<n&&vis[z][o]==0)
            if(dfs[z][o]==s[k][res+1])
            {
                DFS(z,o,k,res+1);
            }
    }
    vis[x][y]=0; //防止搜錯路了,導致下一次用到的時候被標記
    return ;
}
int main()
{
    init();
    while(cin>>n&&n)
    {
        memset(flag,0,sizeof(flag));
        ans.clear();
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
              cin>>dfs[i][j];
        for(int k=0;k<m;k++)
        {
            memset(vis,0,sizeof(vis)); //搜一個單詞的時候清空一次
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                    if(dfs[i][j]==s[k][0])
                    {
                        DFS(i,j,k,0);
                    }
                }
        }
        set<string>::iterator it;
        for(it=ans.begin();it!=ans.end();it++)
            cout<<*it<<endl;
        cout<<"-"<<endl;
    }
    return 0;
}