[SCOI2005]扫雷

相信大家都玩过扫雷的游戏。那是在一个n×m的矩阵里面有一些雷,要你根据一些信息找出雷来。万圣节到了,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目。现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷,如下图:

由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。

输入格式

第一行为N,第二行有N个数,依次为第二列的格子中的数。(1<= N <= 10000)

输出格式

一个数,即第一列中雷的摆放方案数。

 

通过推出的某种dp式,我们可以知道只会存在0,1,2,三种选择

然而,我依然不知道我为什么要写那么多代码

#include<bits/stdc++.h>
#define re return
#define MAX(A,B) ((A)>(B)?(A):(B))
#define inc(i,l,r) for(int i=l;i<=r;++i)
#define dec(i,l,r) for(int i=l;i>=r;--i) 
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

int n,m,f[10005][2][2],a[10005],ans=0;
int main()
{
//    freopen("testdata.in","r",stdin); 
//    freopen("in.txt","r",stdin); 
    rd(n);
    inc(i,1,n)rd(a[i]);
    
    if(n==1)
    {
        if(a[1]==1||a[1]==0)printf("1");
        else printf("0");
        re 0;
    }
    if(a[1]==0)f[2][0][0]=1;
    else if(a[1]==1)f[2][1][0]=f[2][0][1]=1;
    else if(a[1]==2)f[2][1][1]=1;
    
    inc(i,3,n)
    {
        if(!a[i-1])
        f[i][0][0]+=f[i-1][0][0];
        if(a[i-1]==1)
        {
            f[i][0][0]+=f[i-1][0][1];
            f[i][0][1]+=f[i-1][1][0];
            f[i][1][0]+=f[i-1][0][0];
        }
        else if(a[i-1]==2)
        {
            f[i][0][1]+=f[i-1][1][1];
            f[i][1][0]+=f[i-1][0][1];
            f[i][1][1]+=f[i-1][1][0];
        }
        else if(a[i-1]==3)
        {
            f[i][1][1]+=f[i-1][1][1];
        }
    }
    
    if(a[n]==0)ans=f[n][0][0];
    else if(a[n]==1)ans=f[n][0][1]+f[n][1][0];
    else if(a[n]==2)ans=f[n][1][1];
    printf("%d",ans); 
    re 0;
} 

 

posted @ 2019-08-13 21:08  凉如水  阅读(175)  评论(0编辑  收藏  举报