HDU1882(二进制运用)
在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;
}