题目链接:点击打开链接
题意:给你一个4*n的矩阵,你有1*2的砖头若干,让你进行铺砖,在中间m ---- m+k的部分你不用铺。问左边和右边的方法数各位多少。
题解:因为数据偏大,需要滚动数组来优化空间复杂度。其余的就和铺砖块问题一样了。求左右两边各一遍就可以。
状压dp的入门题目的小变形。不会状压DP的可以看一下我的这篇博客,虽然讲的不好,但是代码注释特别详细:https://blog.csdn.net/pk__pk/article/details/79425810
#include<iostream>
#include<cstring>
using namespace std;
const int mod = 997;
int N,M = 4,dp[2][1<<4];
void dfs(int i,int j,int state,int NEXT){
if(j == M){
dp[(i+1)%2][NEXT] += dp[i][state];
dp[(i+1)%2][NEXT] %= mod;
return ;
}
if(state & (1<<j))
dfs(i,j+1,state,NEXT);
if(!(state & (1 << j)))
dfs(i,j+1,state,NEXT|(1<<j));
if(j+1 < M && !((1<<j)&state) && !((1 << (j+1)) &state))
dfs(i,j+2,state,NEXT);
}
int work(int n){
memset(dp,0,sizeof(dp));
dp[1][0] = 1;
for(int i = 1; i <= n ; i ++){
for(int j = 0 ; j < (1 << M ); j ++){
if(dp[i%2][j])
dfs(i%2,0,j,0);
}
for(int j = 0 ; j < (1 << M ) ; j ++)
dp[i%2][j] = 0;
}
return dp[(n+1)%2][0];
}
int main(){
int z;
scanf("%d",&z);
while(z--){
int l,r;
scanf("%d%d%d",&N,&l,&r);
cout << work(l-1) << " " << work(N-l-r+1) << endl;
}
return 0;
}