HDU 1693 Eat the Trees

来源:互联网 发布:穿越火线一键领枪软件 编辑:程序博客网 时间:2024/05/17 22:28

插头DP

只要上下左右边界都没有插头,且每一个可行方格都有两个插头,那内部就一定是联通的。

记f[i][j][k]表示做到第i行,第j列,轮廓线状态为k的方案数

要开long long!

#include<cstdio>#define MAX 15long long f[MAX][MAX][1<<MAX];int map[MAX][MAX];int main(){    int T;    scanf("%d",&T);    for(int n, m, t = 1, limit; t <= T; t++)    {        scanf("%d%d",&n,&m);        limit = 1<<(m+1);        for(int i = 1; i <= n; i++)            for(int j = 1; j <= m; j++)                scanf("%d",&map[i][j]);        f[0][m][0]=1;//排除上边界插头         for(int i = 1; i <= n; i++)        {            for(int k = 0; k < (limit>>1); k++)//继承上一行答案并且排除右边界插头和左边界插头                f[i][0][k<<1]=f[i-1][m][k];            for(int j = 1; j <= m; j++)            {                for(int k = 0; k < limit; k++)                {                    f[i][j][k]=0;                    int x = 1<<(j-1), y=1<<j;//注意:这里的轮廓线是指转移前的轮廓线!                     if(map[i][j])                    {                        f[i][j][k]+=f[i][j-1][k^x^y];                        if(((k&x) && !(k&y)) || (!(k&x) && (k&y)))                            f[i][j][k]+=f[i][j-1][k];                    }                    else                    {                        if((k&x) || (k&y))                            f[i][j][k]=0;                        else f[i][j][k]=f[i][j-1][k];                    }                }            }        }        printf("Case %d: There are %lld ways to eat the trees.\n",t,f[n][m][0]);//排除下边界插头     }}
0 0
原创粉丝点击