• poj 1321 棋盘问题 (状态压缩DP)


    状态方程为dp[i][s]=dp[i-1][s']+dp[i-1][s] (sum[s]<i)

    或dp[i][s]=dp[i-1][s'] (sum[s]==i)

    如果s与base矛盾,则s'必须含有s与base矛盾的项。

    (其中i为第几行,s为状态,s'为是的子状态,base数组记录棋盘状态('.'为1,'#'为0),sum[s]记录s中1的个数)

    View Code
    #include<iostream>
    #include<cstdio>
    #include<string.h>
    using namespace std;
    int n,m;
    int base[10],dp[10][300];
    int state[300],sum[300];
    int main()
    {
        //freopen("test.txt","r",stdin);
        while(~scanf("%d%d",&n,&m))
        {
            if(n==-1&&m==-1)
            return 0;
            int i,j,t,p,k,q;
            memset(base,0,sizeof(base));
            memset(dp,0,sizeof(dp));
            memset(state,0,sizeof(state));
            memset(sum,0,sizeof(sum));
            char str[10];
            for(i=1;i<=n;i++)
            {
                scanf("%s",str);
                for(j=0;j<n;j++)
                {
                    if(str[j]=='.')
                    base[i]+=(1<<j);
                }
            }
            int num=0;
            for(i=0;i<(1<<n);i++)
            {
                k=i;
                while(k)
                {
                    sum[num]+=1&k;
                    k>>=1;
                }
                state[num++]=i;
            }
            dp[0][0]=1;
            for(i=1;i<=n;i++)
            {
                for(j=0;j<num;j++)
                {
                   if(sum[j]>i) continue;
                   if(base[i]&state[j]) //当前状态与base有矛盾
                   {
                       p=base[i]&state[j]; 
                       t=0;
                       q=p;
                       while(p)
                       {
                           if(1&p)
                           t++;
                           p>>=1;
                       }
                       if(t==n) continue;
                       for(t=0;t<n;t++)
                       {
                           if(j&(1<<t))
                           {
                               k=1<<t;
                               if(k&q) continue; 
                               k=j-k;
                               dp[i][j]+=dp[i-1][k];
                           }
                       }
                       if(sum[j]<i) dp[i][j]+=dp[i-1][j];
                   }
                   else
                   {
                       for(t=0;t<n;t++)
                       {
                           if(j&(1<<t))
                           {
                               k=1<<t;
                               k=j-k;
                               dp[i][j]+=dp[i-1][k];
                           }
                       }
                       if(sum[j]<i) dp[i][j]+=dp[i-1][j];
                   }
                }
            }
            int ans=0;
            for(i=0;i<num;i++)
            {
                if(sum[i]==m)
                ans+=dp[n][i];
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    咱家自己的vim配置
    Oauth2手册 第一章
    tcpdf 将网页生成pdf
    Lua 学习记事本
    Lua中的table函数(转)
    Lua常用函数
    将显示对象变成黑白
    Flash 3D 基础
    高等物理:数值积分
    Camera类的基本使用
  • 原文地址:https://www.cnblogs.com/longlongagocsu/p/3043654.html
Copyright © 2020-2023  润新知