去年南京赛区的题目,当时还没学过插头dp,虽然白书上有但一下子无法理解其内涵。
学过以后发现这道题就是个裸题。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF 1e9
#define MAXN 10000
#define MAXM 100
const int maxn = 1005;
const int mod = 1000000007;
#define eps 1e-6
#define pi 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
//ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
using namespace std;
ll d[2][25][1<<11];
int n,m,cur,C,D;
void update(int a,int b,int o1,int n1)
{
if(b & (1<<m)) d[cur][n1][b^(1<<m)] = ( d[cur][n1][b^(1<<m)] + d[1-cur][o1][a]) % mod;
}
char mp[105][15];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d%d%d",&n,&m,&C,&D))
{
// if(n < m) swap(n,m);
rep(i,n) scans(mp[i]);
ini(d);
cur = 0;
d[0][0][(1<<m)-1] = 1;
rep(i,n) rep(j,m)
{
cur ^= 1;
ini(d[cur]);
int tp = mp[i][j] - '0';
if(tp)
{
for(int p = 0;p <= D; p++)
{
for(int k = 0;k < (1<<m); k++)
{
update(k,k<<1,p,p); //bufang
if(i && !(k&(1<<m-1))) update(k,(k<<1)^(1<<m)^1,p,p);
if(j && !(k&1)) update(k,(k<<1)^3,p,p);
if(p && k&(1<<m-1)) update(k,k<<1|1,p-1,p);
}
}
}
else
{
for(int p = 0;p <= D; p++)
{
for(int k = 0;k < (1<<m); k++)
{
if(k&(1<<m-1)) update(k,k<<1|1,p,p);
}
}
}
}
ll ans = 0;
for(int i = C;i <= D; i++)
{
ans = (ans + d[cur][i][(1<<m)-1]) % mod;
}
cout<<ans<<endl;
}
return 0;
}