在DK同学的强烈要求下狂A此题,枚举第一行的所有状态,由于下一行必受上一行约束,则只要判断最后行是否达到要求即可.
总结该题技巧如下:
1、化行为数,将一行数据以二进制形式保存。
2、使用位运算加快速度,^为翻转,&为取值。
3、行列剪枝,若行数小于列数,则使矩阵转置。
代码如下(600多ms ,不知道100MS以内的代码是怎么做到的):
#include
<
iostream
>
using namespace std;
long hash[ 20 ];
long key[ 20 ];
char temp[ 20 ][ 20 ];
int main()
{
long R,C;
while (scanf( " %ld%ld " , & R, & C) != EOF)
{
if (R == 0 && C == 0 )
{
break ;
}
long i,j,k;
for (i = 0 ;i < R; ++ i)
{
scanf( " %s " ,temp[i]);
}
if (R < C)
{
char ttt[ 20 ][ 20 ];
memcpy(ttt,temp, sizeof (temp));
for (i = 0 ;i < R; ++ i)
{
for (j = 0 ;j < C; ++ j)
{
temp[j][i] = ttt[i][j];
}
}
swap(R,C);
}
for (i = 0 ;i < R; ++ i)
{
hash[i] = 0 ;
for (j = 0 ;j < C; ++ j)
{
if (temp[i][j] == ' X ' )
{
hash[i] = (hash[i] << 1 ) ^ 1 ;
}
else
{
hash[i] = (hash[i] << 1 );
}
}
}
long lmax = 1 << (C - 1 );
long total = INT_MAX;
bool finish = false ;
long ct;
long T;
long h = lmax << 1 ;
for (T = 0 ;T < h; ++ T)
{
ct = 0 ;
memcpy(key,hash, sizeof (hash));
for (i = 0 ;i < C; ++ i)
{
if (T & (lmax >> i))
{
key[ 0 ] ^= (lmax >> i);
if (i - 1 >= 0 )
{
key[ 0 ] ^= (lmax >> (i - 1 ));
}
if (i + 1 < C)
{
key[ 0 ] ^= (lmax >> (i + 1 ));
}
if ( 1 < R)
{
key[ 1 ] ^= (lmax >> i);
}
++ ct;
}
}
for (j = 1 ;j < R; ++ j)
{
for (k = 0 ;k < C; ++ k)
{
if (key[j - 1 ] & (lmax >> k))
{
++ ct;
key[j] ^= (lmax >> k);
if (k - 1 >= 0 )
{
key[j] ^= (lmax >> (k - 1 ));
}
if (k + 1 < C)
{
key[j] ^= (lmax >> (k + 1 ));
}
if (j - 1 >= 0 )
{
key[j - 1 ] ^= (lmax >> k);
}
if (j + 1 < R)
{
key[j + 1 ] ^= (lmax >> k);
}
}
}
}
if ( ! key[R - 1 ])
{
finish = true ;
total = total < ct ? total:ct;
}
}
if (finish)
{
printf( " You have to tap %ld tiles.\n " ,total);
}
else
{
printf( " Damaged billboard.\n " );
}
}
return 0 ;
}
using namespace std;
long hash[ 20 ];
long key[ 20 ];
char temp[ 20 ][ 20 ];
int main()
{
long R,C;
while (scanf( " %ld%ld " , & R, & C) != EOF)
{
if (R == 0 && C == 0 )
{
break ;
}
long i,j,k;
for (i = 0 ;i < R; ++ i)
{
scanf( " %s " ,temp[i]);
}
if (R < C)
{
char ttt[ 20 ][ 20 ];
memcpy(ttt,temp, sizeof (temp));
for (i = 0 ;i < R; ++ i)
{
for (j = 0 ;j < C; ++ j)
{
temp[j][i] = ttt[i][j];
}
}
swap(R,C);
}
for (i = 0 ;i < R; ++ i)
{
hash[i] = 0 ;
for (j = 0 ;j < C; ++ j)
{
if (temp[i][j] == ' X ' )
{
hash[i] = (hash[i] << 1 ) ^ 1 ;
}
else
{
hash[i] = (hash[i] << 1 );
}
}
}
long lmax = 1 << (C - 1 );
long total = INT_MAX;
bool finish = false ;
long ct;
long T;
long h = lmax << 1 ;
for (T = 0 ;T < h; ++ T)
{
ct = 0 ;
memcpy(key,hash, sizeof (hash));
for (i = 0 ;i < C; ++ i)
{
if (T & (lmax >> i))
{
key[ 0 ] ^= (lmax >> i);
if (i - 1 >= 0 )
{
key[ 0 ] ^= (lmax >> (i - 1 ));
}
if (i + 1 < C)
{
key[ 0 ] ^= (lmax >> (i + 1 ));
}
if ( 1 < R)
{
key[ 1 ] ^= (lmax >> i);
}
++ ct;
}
}
for (j = 1 ;j < R; ++ j)
{
for (k = 0 ;k < C; ++ k)
{
if (key[j - 1 ] & (lmax >> k))
{
++ ct;
key[j] ^= (lmax >> k);
if (k - 1 >= 0 )
{
key[j] ^= (lmax >> (k - 1 ));
}
if (k + 1 < C)
{
key[j] ^= (lmax >> (k + 1 ));
}
if (j - 1 >= 0 )
{
key[j - 1 ] ^= (lmax >> k);
}
if (j + 1 < R)
{
key[j + 1 ] ^= (lmax >> k);
}
}
}
}
if ( ! key[R - 1 ])
{
finish = true ;
total = total < ct ? total:ct;
}
}
if (finish)
{
printf( " You have to tap %ld tiles.\n " ,total);
}
else
{
printf( " Damaged billboard.\n " );
}
}
return 0 ;
}