hdu4804(轮廓线dp)

题意:给你一个n*m的矩阵(1<=n<=100,1<=m<=10),矩阵里面分为空格和障碍物两种,现在用1*2,2*1,1*1的地板去铺满整个矩阵,且1*1地板所有个数的取值在[c,d]之间(1<=c<=d<=20),问你一共有多少种方法铺满?

代码菜的抠脚,应该把状态转移改成update函数,这样就会好很多

1、我们设dp[cur][g][k]为当前情况已用了g个1*1的板子枚举状态为k的方案数。

2、假设当前(i,j)是障碍物的话,说明我(i,j)这个点不用填东西,并且(i,j)是东西的。

3、假设当前(i,j)是空格的话,我们分情况考虑下:

(1)假设(i,j)我不填东西,说明(i-1,j)是有东西的。

(2)假设(i,j)我填1*1,说明(i-1,j)是有东西的。

(3)假设(i,j)我填(2*1),说明(i-1,j)是没有东西的。

(4)假设(i,j)我填(1*2),说明(i,j-1)是没有东西的,(i-1,j)是有东西的。

 1 #include<string>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;
10 const ll mod=1e9+7;
11 ll dp[2][1<<12][22];
12 int n,m,C,D;
13 char map[105][105];
14 int main()
15 {
16     //freopen("output.txt","w",stdout);
17     int i,j,k,num;
18     while(scanf("%d%d%d%d",&n,&m,&C,&D)!=EOF)
19     {
20         memset(dp,0,sizeof(dp));
21         for(i=0;i<n;i++)scanf("%s",map[i]);
22         int cur=0;
23         dp[cur][(1<<m)-1][0]=1;
24         for(i=0;i<n;i++)
25         {
26             for(j=0;j<m;j++)
27             {
28                 cur^=1;
29                 memset(dp[cur],0,sizeof(dp[cur]));
30                 for(k=0;k<(1<<m);k++)
31                 {
32                     for(num=0;num<=D;num++)
33                     {
34                         if(!dp[cur^1][k][num])continue;
35                         if(map[i][j]==‘1‘)
36                         {
37                             if(j)
38                             {
39                                 if((k&(1<<(m-1)))&&(k&1))
40                                 {
41                                     dp[cur][(k<<1)^(1<<m)][num]+=dp[cur^1][k][num];
42                                     dp[cur][(k<<1)^(1<<m)][num]%=mod;
43                                     if(num^D)dp[cur][((k<<1)^(1<<m))^1][num+1]+=dp[cur^1][k][num],dp[cur][((k<<1)^(1<<m))|1][num+1]%=mod;
44                                 }
45                                 else if((k&(1<<(m-1)))&&(!(k&1)))
46                                 {
47                                     dp[cur][(k<<1)^(1<<m)^3][num]+=dp[cur^1][k][num];
48                                     dp[cur][(k<<1)^(1<<m)^3][num]%=mod;
49                                     dp[cur][(k<<1)^(1<<m)][num]+=dp[cur^1][k][num];
50                                     dp[cur][(k<<1)^(1<<m)][num]%=mod;
51                                     if(num^D)dp[cur][((k<<1)^(1<<m))|1][num+1]+=dp[cur^1][k][num],dp[cur][((k<<1)^(1<<m))|1][num+1]%=mod;
52                                 }
53                                 else if((!(k&(1<<(m-1))))&&(k&1))
54                                 {
55                                     dp[cur][(k<<1)^1][num]+=dp[cur^1][k][num];
56                                     dp[cur][(k<<1)^1][num]%=mod;
57                                 }
58                                 else if((!(k&(1<<(m-1))))&&(!(k&1)))
59                                 {
60                                     dp[cur][(k<<1)^1][num]+=dp[cur^1][k][num];
61                                     dp[cur][(k<<1)^1][num]%=mod;
62                                 }
63                             }
64                             else
65                             {
66                                 if((k&(1<<(m-1))))
67                                 {
68                                     dp[cur][(k<<1)^(1<<m)][num]+=dp[cur^1][k][num],dp[cur][(k<<1)^(1<<m)][num]%=mod;
69                                     if(num^D)dp[cur][(k<<1)^(1<<m)^1][num+1]+=dp[cur^1][k][num],dp[cur][(k<<1)^(1<<m)^1][num+1]%=mod;
70                                 }
71                                 else
72                                 {
73                                     dp[cur][(k<<1)^1][num]+=dp[cur^1][k][num];
74                                     dp[cur][(k<<1)^1][num]%=mod;
75                                 }
76                             }
77                         }
78                         else
79                         {
80                             if(k&(1<<(m-1)))dp[cur][(k<<1)^(1<<m)^1][num]+=dp[cur^1][k][num],dp[cur][(k<<1)^(1<<m)^1][num]%=mod;
81                         }
82                     }
83                 }
84             }
85         }
86         ll ans=0;
87         for(i=C;i<=D;i++)
88         {
89             ans+=dp[cur][(1<<m)-1][i];
90             ans%=mod;
91         }
92         printf("%lld\n",ans);
93     }
94 }
时间: 2024-08-24 14:00:06

hdu4804(轮廓线dp)的相关文章

POJ 3254 Corn Fields (状压DP,轮廓线DP)

题意: 有一个n*m的矩阵(0<n,m<=12),有部分的格子可种草,有部分不可种,问有多少种不同的种草方案(完全不种也可以算1种,对答案取模后输出)? 思路: 明显的状压DP啦,只是怎样压缩状态?跟轮廓线DP一样,按格子为单位来设计状态,一个状态只需要表示到其上方和左方的格子,所以最多只需要保存min(n,m)个01状态就行了(可以尝试旋转一下矩阵),最多需要12位.用哈希表来做会比较快吧,不用去考虑无效的状态,比如出现相邻两个1. 1 //#include <bits/stdc++.

轮廓线DP POJ3254

补了一发轮廓线DP,发现完全没有必要从右往左设置状态,自然一点: 5 6 7 8 9 1 2 3 4 如此设置轮廓线标号,转移的时候直接把当前j位改成0或者1就行了.注意多记录些信息对简化代码是很有帮助的,尤其对于我这种代码经常错的一塌糊涂的人来说.. 呆马: #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath>

轮廓线dp (插头dp)

轮廓线dp 骨牌覆盖问题 n和m比较小 1 #pragma comment(linker, "/STACK:102400000,102400000") 2 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 #include <iostream> 9 #includ

POJ 2411 Mondriaan&#39;s Dream( 轮廓线dp )

最普通的轮廓线dp... 复杂度O(nm2min(n, m)) -------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; #define b(x) (1 << (x)) const in

hdu 5766 Filling 轮廓线dp burnside

Filling 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5766 Description The board is a rectangle of unit cells with N rows and N columns. At first, cells are empty. ?? has infinite blocks with the size of 2*2. ?? can put blocks in the board as long

UVa 11270 铺放骨牌(轮廓线DP)

https://vjudge.net/problem/UVA-11270 题意: 用1×2骨牌覆盖n×m棋牌,有多少种方法? 思路: 这道题目是典型的轮廓线DP题. 所谓轮廓线DP,就是以整行整列为状态进行动态规划时无法进行状态转移,那么此时就可以用到轮廓线,当然,这种方法只能使用在一个窄棋盘上,大了肯定是不行的,要超时! ' 轮廓线DP就是按照从上到下,从左到右的顺序进行状态转移,每个格子用二进制来表示状态,1代表的就是覆盖,0代表未覆盖. 以本题为例,如上图,我们现在要计算 k 格子,那么与

HDU4949 Light (轮廓线dp)

题意:给你一个01矩阵,有两种操作: 第一种: 把a(i,j)的周围四个都异或一下 第二种: 把a(i, j)的周围四个和a(i,j)都异或一下 求把矩阵变成全0矩阵的最少操作次数 思路:如下图所示的轮廓线dp,逐格递推的,cur为当前决策的格子,红色线就是轮廓线,轮廓线以上的格子的操作状态都已经确定了,而对下面状态有影响的只有黄色格子,每个格子保存的是格子当前的数和它自己操作了多少次,因为无论是1还是2操作,对其他格子的影响都是一样的,这样子的复杂度是O(n*m*4^10),明显是会超时的.然

poj 2411 Mondriaan&#39;s Dream (轮廓线DP)

题意:有一个n*m的棋盘,要求用1*2的骨牌来覆盖满它,有多少种方案?(n<12,m<12) 思路: 由于n和m都比较小,可以用轮廓线,就是维护最后边所需要的几个状态,然后进行DP.这里需要维护的状态数就是min(n,m).即大概是一行的大小.每次放的时候,只考虑(1)以当前格子为右方,进行横放:(2)以当前格子为下方进行竖放:(3)还有就是可以不放. 3种都是不一样的,所以前面的一种状态可能可以转为后面的几种状态,只要满足了条件.条件是,横放时,当前格子不能是最左边的:竖放时,当前格子不能是

【轮廓线DP】POJ2411-Mondriaan&#39;s Dream

今天美国的院士过来讲课XD以为会很无聊但是谜之好听,而且英语基本上都听懂了的样子?(´▽`) 逃到图书馆来写解题报告 [题目大意] 给出一个m*n的方格,用2*1的骨牌覆盖有几种情况. [思路] 最基础的轮廓线DP.分为三种情况: (1)向上放,必须要满足上面的格子没有被放,且当前不在首行.→新状态=旧状态删去首位,末尾为1: (2)向左放,必须要满足左边的格子和上面的格子都没有放,且当前不在首列.→新状态=旧状态删去首位,末两位微1: (3)不放,必须满足上面的格子没有放.新状态=旧状态删去首

hdu 4804 Campus Design 轮廓线dp

题意: 给出一个n*m的01矩阵,其中要求把矩阵里面的1用1*1或1*2的砖块铺满,矩阵里面的0为障碍物,问使用1*1的砖块数>=c && <=d 的方案有多少种. 限制: 1 <= n <= 100; 1 <= m <= 10; 1 <= c <= d <= 20; 思路: 因为 1 <= m <= 10 所以可以采用轮廓线dp, 具体状态解释在代码中说明. /*hdu 4804 Campus Design 轮廓线dp 题