POJ 1414

找找手感一道题,有些类似于uva此前做过的一道判断照片字母形状的题,利用DFS求联通分量。

这里要格外注意边缘碰到0的情况的讨论,当遍历一个连通分量时,整个连通分量必须遍历完再推出,不可以分几次遍历同一连通分量,这是DEBUG好久得出的教训

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
using namespace std;

const int maxn= 15;
const int INF= 0x3f3f3f3f;

int n, c;
int bd[maxn][maxn];
bool vis[maxn][maxn];
int step[6][2]= {
	{-1, -1}, {-1, 0}, {0, -1}, {0, 1}, {1, 0}, {1, 1}
};

int dfs(int x, int y)
{
	vis[x][y]= 1;
	if (!bd[x][y]){
		return 0;
	}
	int sm= 1;
	int flag= 0;

	for (int i= 0; i< 6; ++i){
		int nx= x+step[i][0], ny= y+step[i][1];
		if (!bd[nx][ny]){
			flag= 1;
		}
		if (bd[x][y]!= bd[nx][ny]){
			continue;
		}
		else if (!vis[nx][ny]){
			int tp= dfs(nx, ny);
			if (!tp){
				flag= 1;
			}
			sm+= tp;
		}
	}

	return flag ? 0 : sm;
}

int main(int argc, char const *argv[])
{
	memset(bd, -1, sizeof(bd));

	while (2== scanf("%d %d", &n, &c) && n){
		int ans= -INF;
		for (int i= 1; i<= n; ++i){
			for (int j= 1; j<= i; ++j){
				scanf("%d", bd[i]+j);
			}
		}
		memset(bd+n+1, -1, sizeof(bd[0]));

		for (int i= 1; i<= n; ++i){
			for (int j= 1; j<= i; ++j){
				if (!bd[i][j]){
					int tmp= 0;
					memset(vis, 0, sizeof(vis));
					bd[i][j]= c;

					for (int x= 1; x<= n; ++x){
						for (int y= 1; y<= x; ++y){
							if (vis[x][y]){
								continue;
							}
							if (c== bd[x][y]){
								tmp-= dfs(x, y);
							}
							else{
								tmp+= dfs(x, y);
							}
						}
					}
					bd[i][j]= 0;
					ans= max(ans, tmp);
				}
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}
posted @ 2021-06-11 15:21  IdiotNe  阅读(39)  评论(0编辑  收藏  举报