题解 玩水

传送门

观察第二个样例,发现每对斜角相同的字母能贡献出一种不同的走法
有一左上一右下这样的相同字母对就一定合法
二维前缀和来做可以 \(O(nm)\)

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1010
#define ll long long
#define pb push_back
//#define int long long

int n, m;
char a[N][N];

namespace force{
	vector<vector<char>> ans;
	vector<char> v;
	void dfs(int x, int y) {
		v.pb(a[x][y]);
		if (x==n && y==m) ans.pb(v);
		if (x<n) dfs(x+1, y);
		if (y<m) dfs(x, y+1);
		v.pop_back();
	}
	void solve() {
		ans.clear(); v.clear();
		dfs(1, 1);
		sort(ans.begin(), ans.end());
		for (int i=2; i<ans.size(); ++i) {
			if (ans[i-2]==ans[i-1] && ans[i-1]==ans[i]) {puts("1"); return ;}
		}
		puts("0");
	}
}

namespace task{
	int sum[N][N], tem[N][N];
	void solve() {
		memset(sum, 0, sizeof(sum));
		memset(tem, 0, sizeof(tem));
		for (int i=1; i<=n; ++i) {
			for (int j=1; j<=m; ++j) {
				sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
				if (i<n && j<m) {
					if (a[i+1][j]==a[i][j+1]) {
						if (sum[i-1][j-1] || tem[i][j-1] || tem[i-1][j]) {puts("1"); return ;}
						else ++sum[i][j], ++tem[i][j];
					}
				}
			}
		}
		puts("0");
	}
}

signed main()
{
	freopen("water.in", "r", stdin);
	freopen("water.out", "w", stdout);

	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i=1; i<=n; ++i) scanf("%s", a[i]+1);
		// force::solve();
		task::solve();
	}
	
	return 0;
}
posted @ 2021-10-04 17:17  Administrator-09  阅读(8)  评论(0编辑  收藏  举报