WA了好久
主要是在一维的情况的时候,我直接判断是否是全*,错误的任务非全*是不可能变全*的。。。。orz 原谅我蒟蒻
dp【i】【st1】【st2】表示操作完第i行后第i行状态为st1 第i+1行状态为st2
然后枚举找出所有能使st1为0的opt来向后更新
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
int R, C;
int dp[10][1<<8][1<<8];
int statu[10];
char maps[10][10];
int st_opt[1<<8][1<<8];
int cnt_opt[1<<8];
int getst( int st, int opt ){
int ans = st;
for( int i = 0; i < C; i++ ){
if( opt & ( 1 << i ) ){
if( i > 0 ) ans ^= ( 1 << ( i - 1 ) );
ans ^= ( 1 << ( i ) );
if( i < C - 1 ) ans ^= ( 1 << ( i + 1 ) );
}
}
return ans;
}
int getcnt( int opt ){
int ans = 0;
for( int i = 0; i < C; i++ ){
if( opt & ( 1 << i ) ){
ans++;
}
}
return ans;
}
void init(){
for( int i = 0; i < ( 1 << C ); i++ ){
for( int j = 0; j < ( 1 << C ); j++ ){
st_opt[i][j] = getst( i, j );
}
}
for( int i = 0; i < ( 1 << C ); i++ ){
cnt_opt[i] = getcnt( i );
}
}
int main(){
int T, Case = 1;
scanf( "%d", &T );
while( T-- ){
scanf( "%d%d", &R, &C );
init();
for( int i = 0; i < R; i++ ){
scanf( "%s", maps[i] );
statu[i] = 0;
for( int j = 0; j < C; j++ ){
if( maps[i][j] == '.' ){
statu[i] |= ( 1 << j );
}
}
}
int ans = MAX;
if( R == 1){
for( int opt = 0; opt < ( 1 << C ); opt++ ){
if( st_opt[statu[0]][opt] == 0 ){
ans = min( ans, cnt_opt[opt] );
}
}
}else{
memset( dp, 0x3f, sizeof( dp ) );
dp[0][statu[0]][statu[1]] = 0;
for( int opt = 0; opt < ( 1 << C ); opt++ ){
dp[0][st_opt[statu[0]][opt]][st_opt[statu[1]][opt]] = min( dp[0][st_opt[statu[0]][opt]][st_opt[statu[1]][opt]],
cnt_opt[opt] ) ;
}
for( int i = 0; i < R - 2; i++ ){
for( int st1 = 0; st1 < ( 1 << C ); st1++ ){
for( int st2 = 0; st2 < ( 1 << C ); st2++ ){
if( dp[i][st1][st2] != MAX ){
for( int opt = 0; opt < ( 1 << C ); opt++ ){
if( st_opt[st1][opt] == 0 ){
dp[i+1][st_opt[st2][opt]][st_opt[statu[i+2]][opt]] = min( dp[i][st1][st2] + cnt_opt[opt],
dp[i+1][st_opt[st2][opt]][st_opt[statu[i+2]][opt]] );
}
}
}
}
}
}
for( int st1 = 0; st1 < ( 1 << C ); st1++ ){
for( int st2 = 0; st2 < ( 1 << C ); st2++ ){
if( dp[R-2][st1][st2] != MAX ){
for( int opt = 0; opt < ( 1 << C ); opt++ ){
if( st_opt[st1][opt] == 0 && st_opt[st2][opt] == 0 ){
ans = min( ans, dp[R-2][st1][st2] + cnt_opt[opt] );
}
}
}
}
}
}
printf( "Case %d: ", Case++ );
if( ans != MAX ){
printf( "%d\n", ans );
}else{
printf( "impossible\n" );
}
}
return 0;
}
/*
100
5 5
*****
*...*
*...*
*...*
*****
1 2
.*
3 3
**.
**.
...
4 4
*...
**..
..**
...*
8 8
********
********
********
********
********
********
********
********
8 8
........
........
........
........
........
........
........
........
8 8
********
********
********
***.****
****.***
***.****
********
*****.**
1 5
..***
*/