题目:http://codeforces.com/contest/228/problem/C
题意:这题题意表示我理解能力弱了??题目就是描述一种分型,将一个正方形平分成4分,任何选几个涂成黑色,然后不断的进行同样的步骤,每次涂色方案与第一次相同,全是黑色的就不用涂了。。。。
分析:对这种类型不大熟悉,并不能一下子看出是状态压缩DP,不过猜得出来是DP,假设f[ i ][ j ][ t ][mask]表示(i,j)这个格子为左上角,长度为2^t的正方形的分型情况,也就是那几个格子是黑色的,然后通过枚举长度,就可以转移了,具体还是比较简单的。。。。
PS:这题想了好久没思路,稍微瞄了一眼题解,想到了思路,然后就开始敲了,敲完后就悲剧了,不断的wa。。。通过看数据,发现好像我理解错了,重新看了几遍题目都不知道哪错了= =,后来不得以看别人代码,才发现第二段没仔细看,并不是只有图上的那种情况是分型。。。。感觉重新敲,最后还由于长度限制小了wa了一次 T_T,能不能再弱点
代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int mm=555;
int f[mm][mm][11];
int i,j,k,l,n,m,ans;
char c;
int check(int x,int y,int l)
{
if(x+l>=n||y+l>=m)return -1;
int d[4]={f[x][y][k-1],f[x][y+l][k-1],f[x+l][y][k-1],f[x+l][y+l][k-1]};
int i,ret,s;
for(i=0;i<4;++i)
if(d[i]<0)return -1;
for(i=0;i<4;++i)
if(d[i]!=15)break;
if(i==4)return 15;
s=d[i];
for(ret=i=0;i<4;++i)
if(d[i]!=15)
{
if(d[i]!=s)return -1;
}
else ret|=1<<i;
if(l!=1&&s!=ret)return -1;
return ret;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(i=0;i<n;++i)
for(j=0;j<m;++j)
{
scanf(" %c",&c);
f[i][j][0]=(c=='*')?15:0;
}
ans=0;
for(k=1;(l=(1<<k))<=n&&l<=m;++k)
for(i=0;i<n;++i)
for(j=0;j<m;++j)
ans+=(f[i][j][k]=check(i,j,l>>1))>-1&&k>1;
printf("%d\n",ans);
}
return 0;
}