J題 Jigglypuff(思維 + 記憶化搜索)

題目

在這裏插入圖片描述

思路

路徑只要經過兩次拆分和兩次合併就是YES

因爲長路徑必定是由短路徑構成的,將最短路徑合併讓自己處於儘可能左上的位置,這樣是最貪心的,也是最優的。

所以找到圖中所有的傾斜點對的合併點,再查看右下角矩陣內是否有合併點,以及當前合併點下面和右邊是否有合併點,就可以判斷當前合併點是否能YES。

兩種特殊情況
在這裏插入圖片描述
一個合併點下,第二個合併點的所有可行解
在這裏插入圖片描述

隊友敲的代碼

#include <bits/stdc++.h>
#define ls o << 1
#define rs o << 1 | 1
using namespace std;
typedef long long ll;
const int maxn = 3000 + 10;
char s[maxn][maxn];
//bool vis[maxn][maxn];
int dp[maxn][maxn];///dp[i][j]  =1表示從(i, j)可以找到下一個交叉路口      = 0 表示不可以
int n, m;
int dfs(int x, int y){
	if(dp[x][y] >= 0) return dp[x][y];
	if(x > n || y > m) return 0;
	int ok = 0;
	if(s[x + 1][y] == s[x][y + 1] && x + 1 <= n && y + 1 <= m) ok = 1;
	ok |= dfs(x + 1, y);
	ok |= dfs(x, y + 1);
	return dp[x][y] = ok;
}
bool check(int x1, int y1, int x2, int y2){
	if(x1 > n || x2 > n || y1 > m || y2 > m) return false;
	return s[x1][y1] == s[x2][y2];
}
int main(){
	memset(dp, -1, sizeof(dp));
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++){
		scanf("%s", s[i] + 1);
	}
	dfs(1, 1);
	//printf("%d\n", dp[1][1]);
	bool ok = false;
	for(int i = 1; i < n; i++){
		for(int j = 1; j < m; j++){
			if(dp[i + 1][j + 1] == 1 && s[i + 1][j] == s[i][j + 1]){
				ok = true;
				break;
			}
			if(check(i + 1, j, i, j + 1) && check(i + 1, j + 1, i + 2, j)){
				ok = true;
				break;
			}
			if(check(i + 1, j, i, j + 1) && check(i, j + 2, i + 1, j + 1)){
				ok = true;
				break;
			}
		}
	}
	if(ok){
		puts("YES");
	}
	else{
		puts("NO");
	}
	return 0;
}

自己造的樣例

前兩個是NO,然後都是YES
/*
2 4
aade
acef

4 4
abcb
debf
gahi
ajkl

3 4
abnq
bcde
hmea

2 3
abc
bcd

7 6
abcdbf
gaibkl
anopqr
stuvwx
yzebcd
eeghij
klmnop

7 6
abcdbf
gaibkl
anopqr
stuvwx
yzabce
efghej
klmnop
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章