已经没办法再简单的状压dp入门练习

来源:互联网 发布:js点击事件隐藏 编辑:程序博客网 时间:2024/06/07 20:39

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

例如:对于一个2*2的棋盘,有两种方法,一种是使用2个1*2的,一种是使用2个2*1的。
分析:此题由于N比较小,所以可以通过状态压缩,去搜索每一个状态,然后根据前一列对后一列的影响,这样我们只要求出第m+1列状态为0的情况的个数,就是正解

accode:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int INF = 0x3f3f3f3f;const int maxn = 100;const int mod = 1e9 + 7;int T, n, m;ll dp[1005][(1 << 5) + 5];void dfs(int i, int j, int state, int nex) {    if (j == n) {        dp[i + 1][nex] += dp[i][state];        //cout << i + 1 << " " << nex << " " << dp[i + 1][nex]<<endl;        dp[i + 1][nex] = dp[i + 1][nex] % mod;        return;    }    if ((state&(1 << (j))) >0) {        dfs(i, j + 1, state, nex);    }    if ((state&(1 << (j))) == 0) {        dfs(i, j + 1, state, (nex | (1 << (j))));    }    if ((state&(1 << (j))) == 0 && (j + 1<n) && ((state&(1 <<( j + 1))) == 0)) {        dfs(i, j + 2, state, nex);    }}int main(){    memset(dp, 0, sizeof(dp));    scanf("%d%d", &n, &m);    dp[1][0] = 1;    //int t = (3 & (1 << (1)));    //cout <<t << endl;    for (int i = 1; i <= m; i++) {        for (int j = 0; j <(1 << (n)); j++) {            dfs(i, 0, j, 0);        }    }    cout << dp[m + 1][0] << endl;    return 0;}
原创粉丝点击