HDOJ - 4559 排兵布阵 DP

     由于一个炮能影响的范围最多到下两行...所以两行两行来DP..而两行的情况直接搜出来..由于n可能是奇数..为了处理方便..n为奇数时..加一行全0的..把n变为偶数...

     数据太弱..自己出了个100*10的全1输入来跑...N久才出来..真正完美的解法还是应该用状态压缩DP...


Program:

#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#define ll long long
#define oo 1000000007
using namespace std;  
struct node
{
       int h[33][2],num;
}a[4005],p;
int n,m,anum,pre[2][4005],prenum; 
int arc[105][12];
int dp[2][4005],ans;
void dfs(int y,int x)
{
       int i,j;
       for (i=1;i<=p.num;i++)
           if (abs(y-p.h[i][0])+abs(x-p.h[i][1])==2) return;
       p.num++;
       p.h[p.num][0]=y;     p.h[p.num][1]=x; 
       a[++anum]=p;  
       for (j=x+1;j<=m;j++) dfs(y,j);
       for (i=y+1;i<=2;i++)
         for (j=1;j<=m;j++)
           dfs(i,j);
       p.num--;
       return;
}
void prework()
{
       int i,j;
       anum=0;
       p.num=0;
       a[++anum]=p;
       for (i=1;i<=2;i++)
         for (j=1;j<=m;j++)
            dfs(i,j);
       return;
}
bool ok(int p,int t)  // 判断当前状态适合当前图否 
{
       int i; 
       for (i=1;i<=a[p].num;i++)
         if (arc[t+a[p].h[i][0]-1][a[p].h[i][1]]==0) return false;
       return true;
}
bool f(int p1,int p2)  // 判断状态间冲突否 
{
       int i,j;
       for (i=1;i<=a[p1].num;i++)
          for (j=1;j<=a[p2].num;j++)
             if (abs(a[p1].h[i][0]-a[p2].h[j][0]-2)+abs(a[p1].h[i][1]-a[p2].h[j][1])==2) return false;
       return true;
}
int main()
{       
       int i,jj,j,t,k,mm; 
       while (~scanf("%d%d",&n,&m))
       {
             prework(); 
             for (i=1;i<=n;i++)
               for (j=1;j<=m;j++)
                  scanf("%d",&arc[i][j]); 
             if (n%2)
             {
                     n++; 
                     for (j=1;j<=m;j++) arc[n][j]=0;
             } 
             mm=k=0;
             for (i=1;i<=anum;i++)
                if (ok(i,1)) 
                {
                       dp[k][i]=a[i].num;
                       pre[k][++mm]=i; 
                }
             prenum=mm;
             for (t=3;t<=n;t+=2)
             {
                     k=1-k; 
                     memset(dp[k],0,sizeof(dp[k]));
                     mm=0;
                     for (i=1;i<=anum;i++)
                     if (ok(i,t))
                     {
                             pre[k][++mm]=i;
                             for (jj=1;jj<=prenum;jj++)
                             {
                                    j=pre[1-k][jj];
                                    if (dp[k][i]<dp[1-k][j]+a[i].num && f(j,i))
                                        dp[k][i]=dp[1-k][j]+a[i].num;  
                             }
                     }
                     prenum=mm;
             }             
             ans=0;
             for (i=1;i<=anum;i++)
                if (dp[k][i]>ans) ans=dp[k][i];
             printf("%d\n",ans);
       }
       return 0;
}


你可能感兴趣的:(HDOJ - 4559 排兵布阵 DP)