nyoj 1273 宣传墙

题目链接:点击打开链接

题意:给你一个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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值