Loj10172 涂抹果酱

题目描述

Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕。蛋糕俯视图是一个 N×M 的矩形,它被划分成 N×M 个边长为 1×1 的小正方形区域(可以把蛋糕当成 NNN 行 MMM列的矩阵)。蛋糕很快做好了,但光秃秃的蛋糕肯定不好看!所以,Sam 要在蛋糕的上表面涂抹果酱。果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为 1,2,31,2,31,2,3。为了保证蛋糕的视觉效果,Admin 下达了死命令:相邻的区域严禁使用同种果酱。但 Sam 在接到这条命令之前,已经涂好了蛋糕第 KKK 行的果酱,且无法修改。
现在 Sam 想知道:能令 Admin 满意的涂果酱方案有多少种。请输出方案数 mod106。若不存在满足条件的方案,请输出 000。

输入格式

输入共三行。
第一行:N,MN, MN,M;
第二行:KKK;
第三行:MMM 个整数,表示第 KKK 行的方案。
字母的详细含义见题目描述,其他参见样例。

输出格式

输出仅一行,为可行的方案总数。

样例

样例输入

2 2 
1 
2 3

样例输出

3

样例说明

方案一方案二方案三
2
1 2
2
3 1
2
3 2

数据范围与提示

对于 30% 的数据,1N×M20;
对于 60% 的数据,1N1000,1M3;
对于 100% 的数据,1N10000,1M5。

 
这道题用状压DP,是三维的,有很多细节要注意处理。
其中我用了比较笨的储存方法,但是能有效地忽略掉特殊行。
具体看代码,不懂评论。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
#define MAXN 100010
#define INF 10000009
#define MOD 1000000
#define LL long long    
#define in(a) a=read()
#define REP(i,k,n) for(int i=k;i<=n;i++)
#define DREP(i,k,n) for(int i=k;i>=n;i--)
#define cl(a) memset(a,0,sizeof(a))
inline int read(){
    int x=0,f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void out(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) out(x/10);
    putchar(x%10+'0');
}
int n,m,k;
int pow[110]; 
LL f[10010][250];
struct node{
    LL num,a[250];
}tree[10010];
bool check1(int a,int b){
    int sa[6],sb[6],na=m+1,nb=m+1;
    memset(sa,0,sizeof(sa));
    memset(sb,0,sizeof(sb));
    while(a){
        sa[--na]=a%3;
        a/=3;
    }
    while(b){
        sb[--nb]=b%3;
        b/=3;
    }
    REP(i,1,m){
        //cout<<sa[i]<<" "<<sb[i]<<endl;
        if(sa[i]==sb[i])
            return false;}
    return true;
}
bool check2(int a){
    int sa[6],na=m+1;
    memset(sa,0,sizeof(sa));
    while(a){
        sa[--na]=a%3;
        a/=3;
    }
    REP(i,2,m)
        if(sa[i]==sa[i-1])
            return false;
    return true;
}
void init(){
    REP(i,1,n){
        if(i==k)  continue;
        tree[i].num=0;
        REP(j,0,pow[m]-1)
            if(check2(j)){
                tree[i].a[++tree[i].num]=j;
            }
    }
    return ;
}
int DP(){
    LL ans=0;
    REP(i,1,tree[1].num)  f[1][i]=1;
    REP(i,2,n)
        REP(j,1,tree[i].num)
            REP(k,1,tree[i-1].num)
                if(check1(tree[i].a[j],tree[i-1].a[k]))
                {
                    f[i][j]=(f[i][j]+f[i-1][k])%MOD;
                }
    REP(i,1,tree[n].num)  ans=(ans+f[n][i])%MOD;
    return ans;
}
int main(){
    pow[0]=1;
    REP(i,1,10)
        pow[i]=pow[i-1]*3;
    in(n);in(m);in(k);
    tree[k].num=1;
    REP(i,1,m){
        int x;
        in(x);
        x-=1;
        tree[k].a[1]+=x*pow[m-i];
    }
    if(!check2(tree[k].a[1])){
        cout<<0;
        return 0;
    }
    init();
    /*REP(i,1,n){
        REP(j,1,tree[i].num)
            cout<<tree[i].a[j]<<" ";
        cout<<endl;
    }*/
    cout<<DP()<<endl;
    /*REP(i,1,n){
        REP(j,1,tree[i].num)
            cout<<f[i][j]<<" ";
        cout<<endl;
    }*/
    return 0;    
} 

 

posted @ 2018-09-12 18:38  Dijkstra·Liu  阅读(632)  评论(1编辑  收藏  举报