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;
}
posted @ 2008-08-12 03:31  Hdu-Lost  阅读(352)  评论(0编辑  收藏  举报