InputThere are several test cases, please process till EOF. Each test case starts with a line containing four integers N(1 <= N <= 100), M(1 <= M <= 10), C, D(1 <= C <= D <= 20). Then following N lines, each being a string with the length of M. The string consists of ‘0’ and ‘1’ only, where ‘0’ means the square should not be covered by any brick, and ‘1’ otherwise.OutputPlease print one line per test case. Each line should contain an integers representing the answer to the problem (mod 10 9 + 7).Sample Input
1 1 0 0 1 1 1 1 2 0 1 1 1 2 1 1 2 1 2 11 1 2 0 2 01 1 2 0 2 11 2 2 0 0 10 10 2 2 0 0 01 10 2 2 0 0 11 11 4 5 3 5 11111 11011 10101 11111Sample Output
0 0 1 1 1 2 1 0 2 954非常综合的一道轮廓线dp。开始给出已经存在的瓷砖位置,然后用1×1和1×2两种瓷砖铺满地面,其中1×1瓷砖又有限制。只需在状态中加一维表示1×1瓷砖个数,然后利用状压判断当前状态能否填满当前行即可。#include<bits/stdc++.h> #define MAX 102 #define MOD 1000000007 typedef long long ll; using namespace std; int n,m; char s[MAX][12]; int a[MAX]; ll dp[MAX][1<<10][22]; struct Node{ int pre,now,c; }node; vector<Node> v; void dfs(int pos,int pre,int now,int c){ if(pos>m) return; if(pos==m){ node.pre=pre; node.now=now; node.c=c; v.push_back(node); return; } dfs(pos+2,(pre<<2)|3,(now<<2)|3,c); //横放1×2 dfs(pos+1,pre<<1,(now<<1)|1,c); //竖放1×2 dfs(pos+1,(pre<<1)|1,now<<1,c); //不放 dfs(pos+1,(pre<<1)|1,(now<<1)|1,c+1); //加入1×1 } int main() { int t,i,j,k; int c,d; while(~scanf("%d%d%d%d",&n,&m,&c,&d)){ v.clear(); dfs(0,0,0,0); for(i=1;i<=n;i++){ scanf(" %s",s[i]+1); } memset(dp,0,sizeof(dp)); dp[0][(1<<m)-1][0]=1; for(i=1;i<=n;i++){ for(j=0;j<v.size();j++){ int f=0; for(k=1;k<=m;k++){ if(v[j].now&(1<<(m-k))){ if(s[i][k]=='0'){ f=1; break; } } } if(f==1) continue; int now=v[j].now; for(k=1;k<=m;k++){ if(s[i][k]=='0'){ now|=1<<(m-k); } } for(k=0;k<=20;k++){ if(k+v[j].c>20) break; dp[i][now][k+v[j].c]+=dp[i-1][v[j].pre][k]; dp[i][now][k+v[j].c]%=MOD; } } } ll ans=0; for(i=c;i<=d;i++){ ans+=dp[n][(1<<m)-1][i]; ans%=MOD; } printf("%I64d\n",ans); } return 0; }
转载于:https://www.cnblogs.com/yzm10/p/9687580.html
