程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 1038 - Bugs Integrated, Inc. 三進制狀態DP

POJ 1038 - Bugs Integrated, Inc. 三進制狀態DP

編輯:C++入門知識

每個點有三個狀態...不放家伙..放橫的.放豎的..雖然看上去狀態有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 505
using 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;
}

 


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved