/*
宣传墙
时间限制: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
宣传墙
时间限制: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;
}