HDOJ 2640 - Toy bricks 状态压缩DP

     这道题和炮兵阵地很像,不同的是炮兵阵地是每个炮兵不能相互干扰..这题是每个块不能有交集...处理起来稍微麻烦点...


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<set>
#include<algorithm>
#include<cmath>
#define oo 1000000007
#define ll long long
#define pi acos(-1.0)
#define MAXN 505
using namespace std; 
char s[105][10];
int n,m,dp[105][105][105],canuse[105],w[105],num;
bool legal(int x)
{
      int a[10],i,p=x; 
      w[num+1]=0;
      for (i=1;i<=m;i++) w[num+1]+=p%2,p/=2;
      a[0]=0; 
      for (i=1;i<=m;i++)
      {
             a[i]=x%2;
             x/=2;
             if (a[i])
             {
                  if (i-1<1 || i+1>m) return false;
                  if (a[i-1]) return false;
                  if (a[i-2]) return false;
             }
      }
      return true;
}
bool canput(int x,int r)
{
      int i,a[10];
      x=canuse[x]; 
      memset(a,0,sizeof(a));
      for (i=1;i<=m;i++)
      { 
             if (x%2) 
             {
                  a[i-1]=a[i]=a[i+1]=1;
                  if (s[r-1][i]=='#' || s[r+1][i]=='#') return false;
             } 
             x/=2;
      }
      for (i=1;i<=m;i++)
         if (a[i] && s[r][i]=='#') return false; 
      return true;
}
bool ok(int x,int y,int tp)
{ 
      int i,s[2][10];
      x=canuse[x],y=canuse[y];
      if (tp==2)
      {
             while (x && y)
             {
                   if (x%2 && y%2) return false;
                   x/=2,y/=2;
             }
             return true;
      }     
      memset(s,0,sizeof(s)); 
      for (i=1;i<=m;i++)
      {
            if (x%2) s[1][i-1]++,s[1][i]++,s[1][i+1]++,s[0][i]++;
            if (y%2) s[0][i-1]++,s[0][i]++,s[0][i+1]++,s[1][i]++;
            x/=2,y/=2; 
      } 
      for (i=1;i<=m;i++)
         if (s[1][i]>1 || s[0][i]>1) return false;
      return true;
}
int main()
{ 
      int t,i,j,x,r,ans; 
      scanf("%d",&t);
      while (t--)
      {
             scanf("%d%d",&n,&m);
             for (i=1;i<=n;i++) scanf("%s",s[i]+1);
             num=0;
             for (i=0;i<(1<<m);i++)
                if (legal(i)) canuse[++num]=i;
             memset(dp,0,sizeof(dp));
             for (r=2;r<n;r++)
                for (i=1;i<=num;i++)
                   if (canput(i,r))
                     for (j=1;j<=num;j++)
                        if (ok(i,j,1))
                          for (x=1;x<=num;x++) 
                            if (ok(i,x,2))
                               dp[r][j][i]=max(dp[r][j][i],dp[r-1][x][j]+w[i]); 
             ans=0;
             for (i=1;i<=num;i++) 
                for (j=1;j<=num;j++)
                   ans=max(ans,dp[n-1][i][j]);
             printf("%d\n",ans);
      }
      return 0;
}


你可能感兴趣的:(HDOJ 2640 - Toy bricks 状态压缩DP)