zoukankan      html  css  js  c++  java
  • poj 3254(状态压缩DP)

    poj  3254(状态压缩DP)

    题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)

    解析:根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛。首先很容易看到,每一行的状态要符合牧场的硬件条件,即牛必须放在能放牧的方格上。这样就能排除一些状态。另外,牛与牛之间不能相邻,这样就要求每一行中不能存在两个相邻的1,这样也能排除很多状态。然后就是根据上一行的状态转移到当前行的状态的问题了。必须符合不能有两个1在同一列(两只牛也不能竖着相邻)的条件。这样也能去掉一些状态。第i行为某状态state时的方案数为第i-1行的所有符合条件的状态的方案数的总和。

    状态表示:dp[state][i]:在状态为state时,到第i行符合条件的可以放牛的方案数

    状态转移方程:dp[state][i] =Sigma dp[state'][i-1] (state'为符合条件的所有状态)

    DP边界条件:首行放牛的方案数dp[state][1] =1(state符合条件) OR 0 (state不符合条件)

    利用位运算可以巧妙的判断某些状态是否符合条件:

    if(a&(a<<1)==1),用于判断a中相邻位是否同为1,等式成立表示存在,否则不存在;

    if(a&b),用于判断a和b相同位是否同为1,等式成立表示存在,否则不存在。

    AC代码如下:

     1 #include<stdio.h>
     2 #define M 100000000
     3 int dp[13][1<<13],state[1<<13],cur[13];
     4 int m,n,top=0;
     5 void init()        //预处理所有满足条件(相邻位置不能放牛)的状态
     6 {
     7     int i,sum=1<<n;
     8     for(i=0;i<sum;i++)
     9         if(i&(i<<1))
    10             continue;
    11         else
    12             state[top++]=i;
    13 }
    14 int fit(int a,int b)   //判断二进制数相同位置是否同为1
    15 {
    16     if(a&b)
    17         return 0;
    18     return 1;
    19 }
    20 void DP()
    21 {
    22     int i,j,k;
    23     for(i=0;i<top;i++)        //初始化第一行
    24         if(fit(state[i],cur[1]))
    25             dp[1][i]=1;
    26     for(i=2;i<=m;i++)
    27         for(j=0;j<top;j++)   //遍历第i行所有状态
    28         {
    29             if(!fit(cur[i],state[j]))     //若该状态不符合条件
    30                 continue;
    31             else
    32             {
    33                 for(k=0;k<top;k++)      //遍历第i-1行所有状态,找出满足条件的
    34                 {
    35                     if(!fit(state[k],cur[i-1]))  //这一句其实不用也可以
    36                         continue;
    37                     if(!fit(state[k],state[j]))   //若相邻位置同为1,不符合条件
    38                         continue;
    39                     dp[i][j]=(dp[i][j]+dp[i-1][k])%M;   //dp[state][i] =Sigma dp[state'][i-1] (state'为符合条件的所有状态)
    40                 }
    41             }
    42         }
    43     int ans=0;
    44     for(i=0;i<top;i++)          //求最后一行所有满足条件的状态
    45         ans=(ans+dp[m][i])%M;
    46     printf("%d
    ",ans);
    47 }
    48 int main()
    49 {
    50     int x,i,j;
    51     scanf("%d%d",&m,&n);
    52     for(i=1;i<=m;i++)
    53         for(j=1;j<=n;j++)
    54         {
    55             scanf("%d",&x);
    56             if(x==0)        //如果该位置不能放牛,则将该行变成相应的二进制数,方便判断
    57                 cur[i]+=1<<(n-j);
    58         }
    59     init();
    60     DP();
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    Android 8.0 adb shell dumpsys activity activities | findstr mFocusedActivity 获取当前的 activity 显示空的
    spring-in-action_day01
    spring-in-action_day02
    spring-in-action-day04-配置属性 @ConfigurationProperties
    springmvc接收参数
    spring中Utils工具类注入问题
    Eclipse Push出现rejected
    Eclpis-cannot open git-receive-pack
    IO
    LinkedHashmap简要说明
  • 原文地址:https://www.cnblogs.com/frog112111/p/3232941.html
Copyright © 2011-2022 走看看