[HDU1693] Eat the Trees (插头DP)

由周自神讲的插头DP模板题,人生第一道插头DP题纪念一下

状态非常简单,只用0,1即可,

要注意行间转移时不能(要是数组够用这么干也可以,因为DP中不会考虑到这个状态,所以对答案无影响):

 for(int j=0;j<bin[m+1];j++) 

这样会把上一层状态的最后一个搞到下一层造成累赘

正确应为:

for(int j=0;j<bin[m];j++)

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<cstring>
#define int long long
#define m(a) memset(a,0,sizeof(a))
#define AA cout<<"Alita"<<endl
using namespace std;
const int N=20;
int S,T,n,m,a[N][N],bin[N],f[N][N][5000];
void Plug(int x,int y)
{
        int p1=bin[y-1],p2=bin[y];
        for(int i=0;i<bin[m+1];i++)
        {
                int l=i&p1,r=i&p2;
                if(!a[x][y])
                {
                        if((!l)&&(!r)) f[x][y][i]+=f[x][y-1][i]; //继承
                        else f[x][y][i]=0; //非法
                }
                else
                {
                        if(l&&r) f[x][y][i^p1^p2]+=f[x][y-1][i]; //连接
                        else if(l||r)
                        {
                                f[x][y][i]+=f[x][y-1][i];  //拐弯
                                f[x][y][i^p1^p2]+=f[x][y-1][i]; //直走
                        }
                        else
                        {
                                f[x][y][i^p1^p2]+=f[x][y-1][i]; //创造
                        }
                }
        }
}
void work()
{
        memset(f,0,sizeof(f));
        scanf("%lld%lld",&n,&m);
        S=0;
        for(int i=1;i<=n;i++)
        {
                for(int j=1;j<=m;j++)
                {
                        scanf("%lld",&a[i][j]);
                        S|=a[i][j];
                }
        }
        if(!S)
        {
                puts("1");
                return;
        }
        f[1][0][0]=1;
        for(int i=1;i<=n;i++)
        {
                for(int j=1;j<=m;j++) Plug(i,j);
                for(int j=0;j<bin[m+1];j++)
                {
                        f[i+1][0][j<<1]=f[i][m][j];
                }
        }
        printf("%lld\n",f[n][m][0]);
}
signed main()
{
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        bin[0]=1;
        for(int i=1;i<=14;i++) bin[i]=bin[i-1]*2;
        scanf("%lld",&T);
        while(T--) work();
        return 0;
}

 

posted @ 2019-07-28 09:55  ATHOSD  阅读(120)  评论(7编辑  收藏  举报