zoukankan      html  css  js  c++  java
  • 铺地砖|状压DP练习

    有一个N*M(N<=5,M<=1000)的棋盘,现在有1*2及2*1的小木块无数个,要盖满整个棋盘,有多少种方式?答案只需要mod1,000,000,007即可。

    //我也不知道这道题的来源QAQ

    N和M的范围本应是相同的,但是题目给出的N的值很小,这就给我们提供了使用状压DP的思路。

    假设第一列已经铺满,则第二列的情况只与第一列对它的影响有关,同理,第三列的情况也只与第二列对它的影响有关,我们可以利用二进制来表示某一列的情况,状态state表示某一列的状态,例如state=4,则此列状态为00100,用dp[i][state]表示第i列,第i-1列对它的影响为state的方案数,求每一列的方案数可以通过搜索来实现,dp[i][state]=sigma(dp[i-1][la]) la可以通过填放变为state。

    代码:

     1 //铺棋盘
     2 //2015/10/22 
     3 #include<cstdio>
     4 #include<iostream>
     5 #include<cstdlib>
     6 #include<cmath>
     7 #include<vector>
     8 #include<cstring>
     9 #include<algorithm>
    10 #define maxn 100000000+50
    11 #define inf 0x7fffffff
    12 #define  xiao 1e-9
    13 #define mod 1000000007
    14 using namespace std;
    15 int dp[1005][40],n,m;
    16 void dfs(int i,int j,int state,int next)
    17 {
    18     if(j==n) 
    19     {
    20         dp[i+1][next]+=dp[i][state];
    21         dp[i+1][next]%=mod; 
    22         return;
    23     }//如果枚举到了最后一行,则下一列状态为next时方案数加上此列状态为state的方案数
    24     if(((1<<j)&state)>0) dfs(i,j+1,state,next);//如果第j行位置已被占用,直接跳过,搜索j+1行
    25     if(((1<<j)&state)==0) dfs(i,j+1,state,next|(1<<j));//如果未被占用,尝试填放一个1*2的
    26     if(j+1<n&&((1<<j)&state)==0&&((1<<(j+1)&state)==0)) dfs(i,j+2,state,next);//如果此位置以及下一位置都未被占用,尝试放一个2*1的
    27     return;
    28 }
    29 int main()
    30 {
    31     cin>>n>>m;
    32     memset(dp,0,sizeof(dp));
    33     dp[1][0]=1;
    34     for(int i=1;i<=m;++i)
    35       for(int j=0;j<(1<<n);++j)
    36         {
    37             if(dp[i][j])  dfs(i,0,j,0);
    38                     }
    39     cout<<dp[m+1][0]<<endl;
    40     return 0;
    41  } 
  • 相关阅读:
    要养成记录技术问题的习惯
    js排序方法
    阶乘算法练习
    简易的自定义滚动条加鼠标滑轮事件结合使用
    等虚线框的拖拽
    照片墙效果
    苹果导航菜单效果
    简易封装js库
    JQ 实现切换效果
    三级菜单
  • 原文地址:https://www.cnblogs.com/TYH-TYH/p/4899889.html
Copyright © 2011-2022 走看看