1273-宣传墙(第九届河南省ICPC省赛 --状压DP)

题目描述:

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
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f3f
const int mod=997;
using namespace std;
int N,M=4;
int dp[2][1<<4];
void dfs(int i,int j,int state,int next)
{//i表示当前摆放第i列,j表示当前摆放第i行
 //state表示第i列当前状态,next表示对下一列的影响
    if(j==M)//
    {
        dp[(i+1)%2][next]+=dp[i][state];
        //所有可以到达next状态的摆放数之和
        dp[(i+1)%2][next]%=mod;
        return;
    }
    if(state&(1<<j))
        dfs(i,j+1,state,next);
    if(!((1<<j)&state))//某个位置为空,防1*2的
        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);
    //同一列某一位置为空且下一行也为空,防2*1的
}
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 t;
//    printf("%d %d",0&1,1|1);
    scanf("%d",&t);
    while(t--)
    {
        int l,r;
        scanf("%d%d%d",&N,&l,&r);
        printf("%d %d\n",work(l-1),work(N-l-r+1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Kuguotao/article/details/89318868