51nod_棋盘行走 ( 深度优先搜索 )

文章目录

  • 题意
  • 题解
  • 代码
    • 方向遍历方式一
    • 方向遍历方式二
  • 原样

题目连接

题意

给一个 n*m 的棋盘, 棋盘每个格子颜色都是一个大写字母,
以一个格子为起点, 每次只能走上下左右四个方向, 并且每个格子只能走一次,
要求 :
至少经过四个颜色相同的不同格子最终走回起点
若可以输出 Yes, 否则 No.

题解

直接 dfs, 一直忘记回溯起点, wa到蹦! 唉…
后来考虑了下, 的确完全没必要用一个数组来只标记一个起点, 实在是非常浪费,
完全可以用 vis[i][j] = -1 来标记起点,
再或者用两个变量记录起点横纵坐标, 在递归出口的时候判断下即可 …
不过为了强迫症式的整洁, 我就不改了 ^ _ ^

就当复习了 dfs 了吧, 顺便用一用 get 到的新技能, 不用方向数组来枚举方向, emm, 很巧妙啊, 见方向遍历方式二

代码

方向遍历方式一

#include 
using namespace std; 

const int MAXN = 55;

int n, m;
char a[MAXN][MAXN];
bool vis[MAXN][MAXN];
bool isStratPos[MAXN][MAXN];

bool ans = false; 

int nxt[4][2] = {   
    { 0, 1 },
    { 1, 0 }, 
    { 0, -1 },
    { -1, 0 } };

void dfs ( char ch, int x, int y, int len ) {

	if ( ans ) return;

    for ( int k = 0; k < 4; ++k ) {
        int tx = x+nxt[k][0], ty = y+nxt[k][1];
        if ( isStratPos[tx][ty] && len>3 ) { 
            ans = true; 
            return; 
        }
        if ( tx>=n || tx<0 || ty>=m || ty<0 || vis[tx][ty] || ch!=a[tx][ty] ) 
            continue;
        vis[tx][ty] = true;
        dfs ( ch, tx, ty, len+1 ); 
        vis[tx][ty] = false;
    }

}
int main ( ) {

	memset ( vis, false, sizeof(vis) );
    memset ( isStratPos, false, sizeof(isStratPos) );

	cin >> n >> m;
	for ( int i = 0; i < n; ++i ) 
        cin >> a[i];

	for ( int i = 0; i < n; ++i ) {
		for ( int j = 0; j < m; ++j ) {
            isStratPos[i][j] = true;
            vis[i][j] = true;
			dfs ( a[i][j], i, j, 1 );
			if ( ans ) break;
			vis[i][j] = false;
            isStratPos[i][j] = false;
		}
		if ( ans ) break;
    }

    cout << ( ans ? "Yes" : "No") << endl;

	return 0;
}

方向遍历方式二

#include 
using namespace std; 

const int MAXN = 55;

int n, m;
char a[MAXN][MAXN];
bool vis[MAXN][MAXN];
bool isStratPos[MAXN][MAXN];

bool ans = false; 

void dfs ( char ch, int x, int y, int len ) {

	if ( ans ) return;

    for ( int i = -1; i <= 1; ++i ) {     //    -1 :  _  0  _
        for ( int j = -1; j <= 1; ++j ) { //     0 : -1  _  1
            if ( i==j || i&&j ) continue; //     1 :  _  0  _
            int tx = x+i, ty = y+j;
            if ( isStratPos[tx][ty] && len>3 ) { 
                ans = true; 
                return; 
            }
            if ( tx>=n || tx<0 || ty>=m || ty<0 || vis[tx][ty] || ch!=a[tx][ty] ) 
                continue;
            vis[tx][ty] = true;
            dfs ( ch, tx, ty, len+1 ); 
            vis[tx][ty] = false;
        }
    }

}
int main ( ) {

	memset ( vis, false, sizeof(vis) );
    memset ( isStratPos, false, sizeof(isStratPos) );

	cin >> n >> m;
	for ( int i = 0; i < n; ++i ) 
        cin >> a[i];

	for ( int i = 0; i < n; ++i ) {
		for ( int j = 0; j < m; ++j ) {
            isStratPos[i][j] = true;
            vis[i][j] = true;
			dfs ( a[i][j], i, j, 1 );
			if ( ans ) break;
			vis[i][j] = false;
            isStratPos[i][j] = false;
		}
		if ( ans ) break;
    }

    cout << ( ans ? "Yes" : "No") << endl;

	return 0;
}

原样

小Biu在玩一个棋盘游戏,这个游戏给出一个n*m的棋盘,并且每个点上有一个棋子,棋子的颜色用一个大写字母表示。

小Biu获得游戏胜利的条件是:

1.选择一个棋子作为起点。

2.每次只能走上下左右四个方格,并且下一步方格的颜色要与当前格颜色相同

3.每个块只能经过一次,要经过不少于4个不同的格子而且最终要走回起点。

问小Biu是否可以赢得游戏的胜利

输入
第一行包含两个整数n和m (2≤n,m≤50):棋盘的行和列。
接下来n行,每行包含一个有m个字母的串,表示当前行每一个点的颜色。每一个字母都是大写字母。
输出
如果小Biu可以获得胜利输出Yes,否则输出No。
数据范围
对于20%的数据,n *m<=10;
对于65%的数据,n *m<=100;
对于100%的数据, n *m<=2500;
输入样例

3 4
AAAA
ABCA
AAAA

输出样例

Yes

样例解释
样例中所有的’A’形成一个环。

你可能感兴趣的:(#,图论)