UESTC 1690 这是一道比CCCC简单题难的简单题 状态压缩dp

这是一道比CCCC简单题难的简单题
Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/262140KB (Java/Others)


Submit  Status
集训队的CFT大爷精通Python
有一天,CFT大爷跑在vps上的python爬虫程序挂了
CFT大爷经过缜密的推断,发现程序挂了的原因是Python的垃圾回收机制不够优越,导致内存炸了,那些卖vps的奸商强行杀掉了他的爬虫程序
CFT大爷决定再也不用python这门垃圾语言,他要发明一个新的语言CFTthon
CFT大爷的CFTthon是跑在CFT大爷以前写的CFT_OS上的,在CFT_OS中,内存布局是一个n*m的长方形矩阵,而CFTthon所有的变量,都只占用1*2大小的小长方形内存空间。
CFT大爷在手写CFTthon的GC系统时,想到了一个问题:给定n,m,要求用CFTthon的变量把整个内存空间完全覆盖,不重合不遗漏,有多少种方法呢?
**** 扯淡题意分割线 ****
给定一个n*m的矩阵,使用1*2的小长方形覆盖矩阵,要求完全覆盖的同时不出现重合,也不允许超出边界,问有多少种可能的覆盖方法,方案数对1e9+7取模
2<=n<=1000
3<=m<=5

Input
整数n,m


Output
方案数


Sample input and output
Sample Input Sample Output
2 4                                 5
Hint
注意取模


Source

2017 UESTC Training for Dynamic Programming

UESTC 1690 这是一道比CCCC简单题难的简单题 


My Solution

状态压缩dp经典例题
hihoCoder 1048 : 状态压缩·二

这里有更好的讲解。

时间复杂度 O(n*m*(1<<m))
空间复杂度 O(2*(1<<m))


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int MAXN = 5;
const int MOD = 1e9 + 7;

int dp[2][1 << MAXN];
inline int mod(int x)
{
    return x - x / MOD * MOD;
}
int main()
{
    #ifdef LOCAL
    freopen("6.in", "r", stdin);
    //freopen("l.out", "w", stdout);
    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, m, x, i, j, k;
    scanf("%d%d", &n, &m);
    if(n < m) swap(n, m);
    x = 1;
    dp[0][(1 << m) - 1] = 1;
    for(i = 0; i < n; i++){
        for(j = 0; j < m; j++, x ^= 1){
            memset(dp[x], 0, sizeof(dp[x]));
            for(k = 0; k < (1 << m); k++){
                if(k & (1 << (m-1))){
                    dp[x][(k << 1) ^ (1 << m)] = mod(dp[x][(k << 1) ^ (1 << m)] + dp[x^1][k]);
                }
                if(i && !(k & (1 << (m-1)))){
                    dp[x][(k << 1) ^ 1] = mod(dp[x][(k << 1) ^ 1] + dp[x^1][k]);
                }
                if(j && (k & (1 << (m-1))) && !(k & 1)){
                    dp[x][(k << 1) ^ (1 << m) ^ 3] = mod(dp[x][(k << 1) ^ (1 << m) ^ 3] + dp[x^1][k]);
                }
            }
        }
    }
    printf("%d\n", dp[x^1][(1 << m) - 1]);
    return 0;
}


  Thank you!

                                                                                                                                            ------from ProLights

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值