NYOJ_1273_宣传墙

/*
宣传墙
时间限制:1000 ms  |  内存限制:65535 KB
难度:4

描述

    ALPHA 小镇风景美丽,道路整齐,干净,到此旅游的游客特别多。CBA 镇长准备在一条道路南 面 4*N 的墙上做一系列的宣传。
    为了统一规划,CBA 镇长要求每个宣传栏只能占相邻的两个方格 位置。但这条道路被另一条道路分割成左右两段。
    CBA 镇长想知道,若每个位置都贴上宣传栏, 左右两段各有有多少种不同的张贴方案。 例如: N=6,M=3, K=2, 左,
    右边各有 5 种不同的张贴方案

输入
    第一行: T 表示以下有 T 组测试数据 ( 1≤T ≤8 )
    接下来有T行, 每行三个正整数 N M K 分别表示道路的长度,另一条道路的起点和宽度
    (1≤ N ,M ≤ 1 000 000, 1≤ K ≤ 100000)
输出
    每组测试数据,输出占一行:两个整数,分别表示左右两段不同的张贴方案数。由于方案总数
    可能很大,请输出对 997 取模后的结果。
样例输入

2
6 3 2
5 3 2

样例输出

5 5
5 1

*/

状态压缩dp,很典型的一个栗子。同时想说,用滚动数组比较好,我们开的数组差一点爆。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int col = 4;
int row;
int dp[900000][1<<4];

void dfs(int r,int c,int pre,int now)
{
	if(c==col)
	{
		dp[r][now] += dp[r-1][pre];
		dp[r][now] %= 997;
		return ;
	}
	if(c+1<=col)
	{
		dfs(r,c+1,pre<<1,(now<<1)|1);
		dfs(r,c+1,(pre<<1)|1 ,now<<1);
	}
	if(c+2<=col)
	{
		dfs(r,c+2,(pre<<2)|3,(now<<2)|3);
	}
}
int main()
{
	int T,N,M,K;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%d",&N,&M,&K);
		row = M - 1;
		if(row<=0)
		{
			printf("0 ");
		}
		else
		{
			memset(dp,0,sizeof(dp));
			dp[0][(1<<col)-1] = 1;
			for(int i=1;i<=row;i++)
			{
				dfs(i,0,0,0);
			}
			printf("%d ",dp[row][(1<<col)-1]);
		}
		row = N - M - K + 1;
		if(row<=0)
		{
			printf("0\n");
		}
		else
		{
			memset(dp,0,sizeof(dp));
			dp[0][(1<<col)-1] = 1;
			for(int i=1;i<=row;i++)
			{
				dfs(i,0,0,0);
			}
			printf("%d\n",dp[row][(1<<col)-1]);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值