题解Luogu P2749 【[USACO5.1]夜空繁星Starry Night】

HASH判重

我的方法可能比较奇怪

注意一定要判断截出来矩形的形状和图形内部其他图形

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 110, M = 510, dx[8] = {1, 1, 1, -1, -1, -1, 0, 0},
		  dy[8] = {-1, 0, 1, -1, 0, 1, -1, 1};
const ll key[5] = {998244353, 1004535809, 1000000007, 1000000009, 123468723167};
char s[N][N], ans[M], c = 'a';
ll ht[M][8][5];
int vis[N][N], k1[M], k2[M], k3[M], k4[M], cnt, n, m;

void dfs(int x, int y)
{
	k1[cnt] = min(k1[cnt], x);
	k2[cnt] = max(k2[cnt], x);
	k3[cnt] = min(k3[cnt], y);
	k4[cnt] = max(k4[cnt], y);
	vis[x][y] = cnt;
	s[x][y] = '0';
	for (int i = 0; i < 8; ++i)
	{
		int tx = x + dx[i], ty = y + dy[i];
		if (~tx && tx < n && ~ty && ty < m && s[tx][ty] == '1') dfs(tx, ty);
	}
}

void hash1(int k)
{
	for (int i = k1[k]; i <= k2[k]; ++i)
		for (int j = k3[k]; j <= k4[k]; ++j)
			for (int p = 0; p < 5; ++p)
				ht[k][0][p] = ((ht[k][0][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash2(int k)
{
	for (int i = k2[k]; i >= k1[k]; --i)
		for (int j = k3[k]; j <= k4[k]; ++j)
			for (int p = 0; p < 5; ++p)
				ht[k][1][p] = ((ht[k][1][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash3(int k)
{
	for (int i = k1[k]; i <= k2[k]; ++i)
		for (int j = k4[k]; j >= k3[k]; --j)
			for (int p = 0; p < 5; ++p)
				ht[k][2][p] = ((ht[k][2][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash4(int k)
{
	for (int i = k2[k]; i >= k1[k]; --i)
		for (int j = k4[k]; j >= k3[k]; --j)
			for (int p = 0; p < 5; ++p)
				ht[k][3][p] = ((ht[k][3][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash5(int k)
{
	for (int j = k3[k]; j <= k4[k]; ++j)
		for (int i = k1[k]; i <= k2[k]; ++i)
			for (int p = 0; p < 5; ++p)
				ht[k][4][p] = ((ht[k][4][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash6(int k)
{
	for (int j = k3[k]; j <= k4[k]; ++j)
		for (int i = k2[k]; i >= k1[k]; --i)
			for (int p = 0; p < 5; ++p)
				ht[k][5][p] = ((ht[k][5][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash7(int k)
{
	for (int j = k4[k]; j >= k3[k]; --j)
		for (int i = k1[k]; i <= k2[k]; ++i)
			for (int p = 0; p < 5; ++p)
				ht[k][6][p] = ((ht[k][6][p] << 1) + (vis[i][j] == k)) % key[p];
}

void hash8(int k)
{
	for (int j = k4[k]; j >= k3[k]; --j)
		for (int i = k2[k]; i >= k1[k]; --i)
			for (int p = 0; p < 5; ++p)
				ht[k][7][p] = ((ht[k][7][p] << 1) + (vis[i][j] == k)) % key[p];
}

int main()
{
	scanf("%d%d", &m, &n);
	for (int i = 0; i < n; ++i) scanf("%s", s[i]);
	memset(k1, 127, sizeof k1);
	memset(k3, 127, sizeof k3);
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < m; ++j)
			if (s[i][j] == '1') ++cnt, dfs(i, j);
	for (int i = 1; i <= cnt; ++i)
	{
		hash1(i);
		hash2(i);
		hash3(i);
		hash4(i);
		hash5(i);
		hash6(i);
		hash7(i);
		hash8(i);
	}
	for (int i = 1; i <= cnt; ++i)
		if (!ans[i])
		{
			ans[i] = c++;
			for (int j = i + 1; j <= cnt; ++j)
				if (k2[j] - k1[j] == k2[i] - k1[i]
					|| k2[j] - k1[j] == k4[i] - k3[i]
					|| k4[j] - k3[j] == k2[i] - k1[i]
					|| k4[j] - k3[j] == k4[i] - k3[i])
					for (int k = 0; k < 8; ++k)
					{
						bool flag = true;
						for (int p = 0; p < 5; ++p)
							if (ht[i][0][p] != ht[j][k][p])
							{
								flag = false;
								break;
							}
						if (flag)
						{
							ans[j] = ans[i];
							break;
						}
					}
		}
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < m; ++j)
			putchar(ans[vis[i][j]] ? ans[vis[i][j]] : '0');
		putchar('\n');
	}
	return 0;
}
posted @ 2019-01-21 14:38  面向大海  阅读(135)  评论(0编辑  收藏  举报