1273-宣传墙(状压dp )

1273-宣传墙


内存限制:64MB 时间限制:1000ms 特判: No

通过数:14 提交数:50 难度: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

AC:代码 0ms

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef long long int lli;
typedef unsigned long long llu;

const int maxn = 1<<4;
const int mod = 997;
struct matrix{
	int s[maxn][maxn];
}x;
int n,m,k;
int s1,s2;

matrix MulMatrix(matrix a,matrix b,int c,int d,int e)
{
	matrix res;
	for(int i = 0;i<c;i++){
		for(int j = 0;j<d;j++){
			int x = 0;
			for(int k = 0;k<e;k++){
				x = (x + a.s[i][k] * b.s[k][j])%mod;
			}
			res.s[i][j] = x;
		}
	}
	return res;
}

matrix MatrixPow(matrix a,int b)
{
	matrix res;
	memset(res.s,0,sizeof(res.s));
	for(int i = 0;i<maxn;i++){
		res.s[i][i] = 1;
	}
	while(b)
	{
		if(b&1) res = MulMatrix(res,a,1,maxn,maxn);
		b >>= 1;
		a = MulMatrix(a,a,maxn,maxn,maxn);
	}
	return res;
}

void dfs(int i,int j,int k,int u)//i 行 j 这一列的状态 k 下一列 u (ii) 
{
	if(u == 4){
		x.s[i][k] ++;
		return;
	}
	if((j&(1<<u))){
		dfs(i,j,k,u+1);
		return;
	}
	dfs(i,j|(1<<u),k|(1<<u),u+1);
	if(u+1<4 && !(j&(1<<u)) && !(j&(1<<(u+1)))){
		dfs(i,j|(1<<u)|(1<<(u+1)),k,u+2);
	}
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d %d",&n,&m,&k);
		int s1 = m-1;
		if(s1 == 0){
			printf("0 ");
		} else {
			memset(x.s,0,sizeof(x.s));
			for(int i = 0;i<maxn;i++){
				dfs(i,i,0,0);
			}
			matrix y = MatrixPow(x,s1);
			printf("%d ",y.s[0][0]%mod);
		}
		s2 = n - s1 - k;
		if(s2 == 0){
			printf("0\n");
		} else {
			memset(x.s,0,sizeof(x.s));
			for(int i = 0;i<maxn;i++){
				dfs(i,i,0,0);
			}
			matrix y = MatrixPow(x,s2);
			printf("%d\n",y.s[0][0]%mod);
		}
	}
	return 0;
}

在网上找到了一种简单一点的代码贴一下

#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;  
}


posted @ 2018-06-07 19:26  Nlifea  阅读(102)  评论(0编辑  收藏  举报