搜索_IDA*_POJ4007_Flood-it!

版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84451802

点此打开题目页面

思路分析:

    设L = a_{1}...a_{n}为使得变换次数最少的一个变换序列, 设变换序列A = a_{1}...a_{i - 1}, B = a_{1}...a_{i}, (2 <= i <= n), 则B对应的格局(网格图)左上角的连通块包含A对应格局左上角连通块中所有结点, 且B对应的连通块的结点个数大于A对应的连通块中的结点个数, 因此只需考虑每次变换新增的部分, 设输入格局为G, 维持数组C满足: 如果G[i][j]在左上角连通块那么C[i][j] = 1, 如果G[i][i]与左上角连通块相邻那么C[i][j] = 2, 其它情况C[i][j] = 0, 则每次变换的颜色即为C[i][j] = 2的颜色. 考虑使用IDA*, 因为每次变换至多使得格局中的颜色种类数减少1, 因此可设估价函数为当前格局中颜色种类数减1. 下面给出基于此策略的AC代码:

//CH2912_Flood-it!
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 9, dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
//G: 当前格局(网格状态),C:若G[i][j]在G[1][1]所在连通块则C[i][j] = 1,若在其边缘则为2, 否则为0
char G[MAXN][MAXN], C[MAXN][MAXN]; int N, deep;
//估价函数: 返回G中不同颜色个数减1
int F(){
	bool hav[6] = {false};
	for(int i = 1; i <= N; ++i)
		for(int j = 1; j <= N; ++j) if(C[i][j] != 1) hav[G[i][j]] = true;
	int res = 0; for(int i = 0; i <= 5; ++i) if(hav[i]) ++res; return res;
}
void dfs(int x, int y){
	C[x][y] = 1;
	for(int i = 0; i <= 3; ++i){
		int a = x + dx[i], b = y + dy[i];
		if(a >= 1 && a <= N && b >= 1 && b <= N && C[a][b] != 1)
			if(G[a][b] == G[x][y]) dfs(a, b); else C[a][b] = 2;
	}
}
//将G左上角的颜色设置为col,如果存在某个方块颜色为col,且对应C中元素为2则返回true, 否则返回false  
bool setCol(int col){
	bool res = false;
	for(int i = 1; i <= N; ++i)
		for(int j = 1; j <= N; ++j) if(G[i][j] == col && C[i][j] == 2) res = true, dfs(i, j);
	return res;
}
bool solve(int level){
	int f = F(); 
	if(level + f > deep) return false;
	if(!f) return true;
	int tc[MAXN][MAXN]; memcpy(tc, C, sizeof(C)); 
	for(int i = 0; i <= 5; ++i){
		if(setCol(i) && solve(level + 1)) return true;
		memcpy(C, tc, sizeof(C));
	}	
	return false;	 
}
int main(){
	while(scanf("%d", &N), N){
		for(int i = 1, t; i <= N; ++i)
			for(int j = 1; j <= N; ++j) scanf("%d", &t), G[i][j] = t;
		memset(C, 0, sizeof(C)), dfs(1, 1), deep = 0;
		while(!solve(0)) ++deep; cout << deep << endl;
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/solider98/article/details/84451802