zoukankan      html  css  js  c++  java
  • 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
    ");
    		} 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
    ",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
    ");  
            }  
            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]);  
            }  
        }  
        return 0;  
    }


  • 相关阅读:
    洛谷P2640 神秘磁石(欧拉筛法)
    并查集
    高精度算法
    手写堆
    对拍的使用
    unity4.6学习Ugui中文文档-------参考-UGUI Rect Transform
    使用c#访问脚本里变量的方法
    Unity3d 脚本相互调用
    set_union的几个例子[转]
    C++ 关键字——friend
  • 原文地址:https://www.cnblogs.com/Nlifea/p/11745997.html
Copyright © 2011-2022 走看看