poj 2411 2663 2420 dp+dfs+矩阵快速幂(1*2矩形排版次数)

来源:互联网 发布:桨战船 知乎 编辑:程序博客网 时间:2024/05/20 16:41

从这篇博客学到很多:

点击打开链接

直接枚举高的状态,一旦此状态确定了,之后的状态就都确定了。


poj2411:

题意:

给定一个长宽小于等于11的矩形,问用1×2的小矩形填满,有多少种方法。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 12;int h, w;LL dp[maxn][1 << maxn];vector<pair<int, int> > path;void dfs(int dep, int nowState, int preState){    if (dep > w)        return;    if (dep == w)    {        path.push_back(make_pair(nowState, preState));        return;    }    dfs(dep + 2, (nowState << 2) | 3, (preState << 2) | 3);    dfs(dep + 1, (nowState << 1) | 1, preState << 1);    dfs(dep + 1, nowState << 1, (preState << 1) | 1);}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d", &h, &w))    {        if (!h && !w)            break;        if (h < w)            swap(h, w);        path.clear();        dfs(0, 0, 0);        memset(dp, 0, sizeof(dp));        dp[0][(1 << w) - 1] = 1;        for (int i = 1; i <= h; i++)        {            for (int j = 0; j < path.size(); j++)            {                int now = path[j].first;                int pre = path[j].second;                dp[i][now] += dp[i - 1][pre];            }        }        printf("%lld\n", dp[h][(1 << w) - 1]);    }    return 0;}

poj 2663:

题意:

给定1*2的小矩形,去拼接一个3*n(n<30)的矩形,问有多少种方案。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int inf = 0x3f3f3f3f;typedef vector<LL> vec;typedef vector<vec> mat;int h, w;mat A(20, vec(20));void dfs(int dep, int nowState, int preState){    if (dep > w)        return;    if (dep == w)    {        A[preState][nowState]++;        return;    }    dfs(dep + 2, (nowState << 2) | 3, (preState << 2) | 3);    dfs(dep + 1, (nowState << 1) | 1, preState << 1);    dfs(dep + 1, nowState << 1, (preState << 1) | 1);}mat mul(mat &A, mat &B){    mat C(A.size(), vec(B[0].size()));    for (int i = 0; i < A.size(); i++)    {        for (int k = 0; k < B.size(); k++)        {            for (int j = 0; j < B[0].size(); j++)            {//                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;                C[i][j] = (C[i][j] + A[i][k] * B[k][j]);            }        }    }    return C;}mat pow(mat A, LL n){    mat B(A.size(), vec(A.size()));    for (int i = 0; i < A.size(); i++)    {        B[i][i] = 1;    }    while (0 < n)    {        if (n & 1)            B = mul(B, A);        A = mul(A, A);        n >>= 1;    }    return B;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    w = 3;    dfs(0, 0, 0);    while (~scanf("%d", &h))    {        if (h == -1)            break;        mat ans = pow(A, h);        printf("%lld\n", ans[(1 << w) - 1][(1 << w) - 1]);    }    return 0;}

poj 2420:

题意:

给定1*2的小矩形,去拼接一个4*n(n<10^9)的矩形,问有多少种方案。


解析:

N这么大递推肯定是不行了,所以我们要用矩阵快速幂进行加速,这个转移矩阵如何构造呢,我们可以直接用pre状态转移到now状态采用邻接矩阵的方式表述就好了。这个矩阵的大小为at[16][16],at[15][15]就是最后要求的状态。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define lson lo, mi, rt << 1#define rson mi + 1, hi, rt << 1 | 1using namespace std;const int inf = 0x3f3f3f3f;typedef vector<LL> vec;typedef vector<vec> mat;int h, w;int mod;mat A(20, vec(20));void dfs(int dep, int nowState, int preState){    if (dep > w)        return;    if (dep == w)    {        A[preState][nowState]++;        return;    }    dfs(dep + 2, (nowState << 2) | 3, (preState << 2) | 3);    dfs(dep + 1, (nowState << 1) | 1, preState << 1);    dfs(dep + 1, nowState << 1, (preState << 1) | 1);}mat mul(mat &A, mat &B){    mat C(A.size(), vec(B[0].size()));    for (int i = 0; i < A.size(); i++)    {        for (int k = 0; k < B.size(); k++)        {            for (int j = 0; j < B[0].size(); j++)            {                C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;//                C[i][j] = (C[i][j] + A[i][k] * B[k][j]);            }        }    }    return C;}mat pow(mat A, LL n){    mat B(A.size(), vec(A.size()));    for (int i = 0; i < A.size(); i++)    {        B[i][i] = 1;    }    while (0 < n)    {        if (n & 1)            B = mul(B, A);        A = mul(A, A);        n >>= 1;    }    return B;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    w = 4;    dfs(0, 0, 0);    while (~scanf("%d%d", &h, &mod))    {        if (!h && !mod)            break;        mat ans = pow(A, h);        printf("%lld\n", ans[(1 << w) - 1][(1 << w) - 1]);    }    return 0;}




0 0
原创粉丝点击