POJ 1681 Painter's Problem【状态压缩,枚举】

POJ 1681 Painter's Problem

算法核心:状态压缩,枚举
大意:有一面n*n的墙,对其中某一格子上色,
则其上、下、左、右及自身的颜色均变色,
颜色仅有黄色和白色两种,已知墙面信息,
问能否将墙面全部变为黄色,若能,至少需要涂色几次?

分析:
1.通过状态压缩,枚举第一行的着色网格
2.通过已知的第一行着色状态,根据上层信息依次推得下层着色状态
3.对2退出的第n层着色状态进行判断,若合法,更新当前最小值。

#include < stdio.h >
#include
< string .h >
const int N = 17 ;
const int inf = 99999 ;
bool graph[N][N]; // graph[i][j]存储最初的颜色,黄色为0,白色为1
bool swap[N][N]; // swap[i][j]存储该格是否进行染色
int main()
{
int T;
while (scanf( " %d " , & T) != EOF)
{
while (T -- )
{
int n;
scanf(
" %d " , & n);
long upper = 1 << n;
long cur,i,j;
char str[N];
memset(graph,
0 , sizeof (graph));
for (i = 1 ;i <= n;i ++ )
{
scanf(
" %s " ,str);
for (j = 0 ;j < n;j ++ )
{
if (str[j] == ' w ' )graph[i][j + 1 ] = true ;
}
}
int ans = inf;
for (cur = 0 ;cur < upper;cur ++ ) // 枚举第一行按钮状态
{
memset(swap,
false , sizeof (swap));
long tcur = cur;
for (i = 1 ;i <= n;i ++ )
{
swap[
1 ][i] = cur & 1 ;
cur
>>= 1 ;
}
cur
= tcur;
for (i = 2 ;i <= n;i ++ )
{
for (j = 1 ;j <= n;j ++ )
swap[i][j]
= (graph[i - 1 ][j] ^ swap[i - 1 ][j] ^ swap[i - 1 ][j - 1 ] ^ swap[i - 1 ][j + 1 ] ^ swap[i - 2 ][j]);
}

bool flag = true ;

for (i = 1 ;i <= n;i ++ )
if (swap[n][i] ^ swap[n - 1 ][i] ^ swap[n][i - 1 ] ^ swap[n][i + 1 ] ^ graph[n][i]){
flag
= false ;
break ;
}

if (flag)
{
int step = 0 ;
for (i = 1 ;i <= n;i ++ )
for (j = 1 ;j <= n;j ++ )
if (swap[i][j])
step
++ ;

if (step < ans)ans = step;
}
}

if (ans == inf)printf( " inf\n " );
else
printf(
" %d\n " ,ans);
}

}
return 0 ;
}

你可能感兴趣的:(paint)