zoukankan      html  css  js  c++  java
  • TOJ3112: 单词串串烧(回溯)

    传送门(<--可以点击的)

    时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte

    描述

    “单词串串烧”是一款拼词智力游戏,给定4*4的方格,随机取16个大写字母置于16个方格之中,玩家从任意一个方格出发,从一个字母沿相邻(上、下、左、右,左上、左下、右上、右下8个方向都算相邻)方格可以找到另一字母,将这些字母串联起来可以组成许多不同的单词。现在的问题是先给出一个单词,需要你开动脑筋写一个程序来判断是否能够从这些方格中的字母拼出给定的单词,但要注意:在同一个单词中任何一个方格只能使用1次。
    比如:

    P R G N 
    G O E I 
    R S M Y 
    A M E D

    可以拼出“PROGRAMMING”、“SOME”、“RED”,但不能拼出“PROGRAMMER”,因为最后一个R重复使用了。

    输入

    输入数据有多组,每组数据的第1行为一个由大写字母组成的单词,不超过16个字母。接下来有4行,每行4个大写字母,组成4*4的方格。输入数据以EOF结束。

    输出

    对每组输入数据,判断是否可以拼出该单词,如果可以输出yes,否则输出no。

    样例输入

     

    PROGRAMMING
    PRGN
    GOEI
    RSMY
    AMED
    ROSEMARY
    AMED
    RSMY
    GOEI
    PRGN

    样例输出

     

    yes
    no

    思路:简单回溯题,记录一下第一个字符出现的位置,然后深搜找就行。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<string.h>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map> 
    #include<vector>
    #define ll long long
    using namespace std;
    int go[8][2]={{-1,0},{1,0},{0,-1},{0,1},{1,1},{1,-1},{-1,1},{-1,-1}};
    char ma[10][10];
    bool check(int x,int y){
        if(x < 0 || x >= 4 || y < 0 || y >= 4){
            return false;
        }
        return true;
    }//判断是否越界 
    int vis[4][4],f;
    void dfs(int x,int y,string cmp,string now){
        vis[x][y] = 1;
        if(now.size()+1 ==cmp.size())
            f = 1;
        for(int i = 0 ; i < 8 ; i++){
            int dx = x + go[i][0];
            int dy = y + go[i][1];
            if(!vis[dx][dy] && check(dx,dy) && ma[dx][dy] == cmp[now.size()+1]){
                vis[dx][dy] = 1;
                dfs(dx,dy,cmp,now+ma[dx][dy]);
                vis[dx][dy] = 0;//回溯思想 
            }
        }
    }
    int main(){
        string cmp;
        while(cin>>cmp){
            int ex[100],ey[100],k = 0;
            //这里我用ex ey数组存出现第一个字符的横纵坐标,作为深搜的起点。 
            for(int i = 0 ; i < 4 ; i++){
                scanf("%s",ma[i]);
                for(int j = 0; j < 4 ;j++){
                    if(ma[i][j] == cmp[0]){
                        ex[k] = i;
                        ey[k++] = j;
                    }
                }//记录出现第一个字符的横纵坐标 
            }
            f = 0;//记录是否已经找到 
            for(int i = 0 ; i < k ; i++){
                memset(vis,0,sizeof(vis));//每次清空vis数组
                dfs(ex[i],ey[i],cmp,"");//分别代表 进入深搜的横纵坐标,需要匹配的串,以及空串。 
                if(f)break;
            }
            f?puts("yes"):puts("no");
        }
    }
  • 相关阅读:
    LeetCode 842. Split Array into Fibonacci Sequence
    LeetCode 1087. Brace Expansion
    LeetCode 1219. Path with Maximum Gold
    LeetCode 1079. Letter Tile Possibilities
    LeetCode 1049. Last Stone Weight II
    LeetCode 1046. Last Stone Weight
    LeetCode 1139. Largest 1-Bordered Square
    LeetCode 764. Largest Plus Sign
    LeetCode 1105. Filling Bookcase Shelves
    LeetCode 1027. Longest Arithmetic Sequence
  • 原文地址:https://www.cnblogs.com/Esquecer/p/8671602.html
Copyright © 2011-2022 走看看