POJ 1038 - Bugs Integrated, Inc. 三进制状态DP

来源:互联网 发布:whois域名查询 编辑:程序博客网 时间:2024/06/03 08:29

       每个点有三个状态...不放家伙..放横的.放竖的..虽然看上去状态有3^m..最多3^10=59049种...但把自我矛盾的排除后..一行的可能状态最多280种...

       由于一个方块最多可能影响到上面两层..所以DP需要三维...dp [ r ] [ x ]  [ y ] 代表第r-1行放状态y...第r行放状态x..

       第一次提交爆空间了...把dp的第一维改为滚动的就可以了....

       效率不高...3000MS+过的...有些大神不到1000MS过..有些也是三进制状态DP..10000MS~20000MS过...看来状态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 505using namespace std;   int s[155][15],n,m,canuse[280],w[280],tall[280],dp[2][280][280],num;bool f[280][280][2];bool legal(int x){      int s[15],i,j;       memset(s,0,sizeof(s));       w[num+1]=0;      tall[num+1]=0;      for (i=1;i<=m;i++)      {            if (x%3==1) s[i]++,s[i+1]++,s[i+2]++,tall[num+1]=max(tall[num+1],1);            if (x%3==2) s[i]++,s[i+1]++,tall[num+1]=max(tall[num+1],2);            if (x%3) w[num+1]++;            x/=3;      }      if (s[m+1]) return false;      for (i=1;i<=m;i++)         if (s[i]>1) return false;      return true; }bool canput(int x,int r){       int i;       if (r-tall[x]<1) return false;       x=canuse[x];        for (i=1;i<=m;i++)       {            if (x%3==1 && (s[r][i] || s[r][i+1] || s[r][i+2] || s[r-1][i] || s[r-1][i+1] || s[r-1][i+2])) return false;            if (x%3==2 && (s[r][i] || s[r][i+1] || s[r-1][i] || s[r-1][i+1] || s[r-2][i] || s[r-2][i+1])) return false;             x/=3;       }        return true;}bool ok(int x,int y,int tp){       int a[10][15],i,j;       memset(a,0,sizeof(a));       x=canuse[x],y=canuse[y];       for (i=1;i<=m;i++)       {             if (y%3==1) a[0][i]++,a[0][i+1]++,a[0][i+2]++;             if (y%3==2) a[0][i]++,a[0][i+1]++;             if (x%3==1) a[tp-1][i]++,a[tp-1][i+1]++,a[tp-1][i+2]++;             if (x%3==2) a[tp-1][i]++,a[tp-1][i+1]++,a[tp-2][i]++,a[tp-2][i+1]++;             y/=3,x/=3;       }       for (i=0;i<10;i++)          for (j=0;j<15;j++)             if (a[i][j]>1) return false;       return true;}int main(){         int T,K,totol,r,x,y,i,j,ans;      scanf("%d",&T);      while (T--)      {             scanf("%d%d%d",&n,&m,&K);             memset(s,0,sizeof(s));             while (K--)  scanf("%d%d",&y,&x),s[y][x]=1;             num=0;             totol=1;             for (x=1;x<=m;x++) totol*=3;             for (x=0;x<totol;x++)                 if (legal(x)) canuse[++num]=x;             memset(dp,0,sizeof(dp));             for (r=1;r<=2;r++)               for (i=1;i<=num;i++)                  for (j=1;j<=num;j++)                    f[i][j][r]=ok(i,j,r);             for (r=1;r<=n;r++)              {                 memset(dp[r%2],0,sizeof(dp[r%2]));                 for (i=1;i<=num;i++)                    if (canput(i,r))                      for (j=1;j<=num;j++)                         if (f[i][j][1])                            for (x=1;x<=num;x++)                               if (f[i][x][2])                                   dp[r%2][j][i]=max(dp[r%2][j][i],dp[(r-1)%2][x][j]+w[i]);             }             ans=0;             for (i=1;i<=num;i++)               for (j=1;j<=num;j++)                  ans=max(ans,dp[n%2][i][j]);             printf("%d\n",ans);       }      return 0;}


原创粉丝点击