BZOJ1088 [SCOI2005]扫雷Mine 动态规划

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1088


 

题意概括

  扫雷。只有2行。第2行没有雷,第一行有雷。告诉你第二行显示的数组,问有几种摆放方式。


 

题解

  动态规划。

  用dp[i][0][0]表示当前位置为0,前一位置为0的方案总数,

  用dp[i][0][1]表示当前位置为1,前一位置为0的方案总数,

  用dp[i][1][0]表示当前位置为0,前一位置为1的方案总数,

  用dp[i][1][1]表示当前位置为1,前一位置为1的方案总数,

  然后分各种情况转移即可。

  网上又说直接模拟的——代码比我短好多!都是大佬!Orz


代码

#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N=10000+5;
int n,a[N];
LL dp[N][2][2];
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
        if (a[i]>3)
            {printf("0");return 0;}
    if (a[1]>2||a[n]>2)
        {printf("0");return 0;}
    memset(dp,0,sizeof dp);
    if (a[1]==0)
        dp[1][0][0]=1;
    else if (a[1]==1)
        dp[1][0][0]=dp[1][0][1]=1;
    else if (a[1]==2)
        dp[1][0][1]=1;
    for (int i=2;i<=n;i++){
        int v=a[i-1];
        LL p00=dp[i-1][0][0],p01=dp[i-1][0][1],p10=dp[i-1][1][0],p11=dp[i-1][1][1];
        LL &n00=dp[i][0][0],&n01=dp[i][0][1],&n10=dp[i][1][0],&n11=dp[i][1][1];
        if (a[i]==0){
            if (v>1)
                {printf("0");return 0;}
            if (v==1)
                n00+=p10;
            else if (v==0)
                n00+=p00;
        }
        else if (a[i]==1){
            if (v==3)
                {printf("0");return 0;}
            if (v==2)
                n10+=p11,n01+=p10;
            else if (v==1)
                n10+=p01,n01+=p00,n00+=p10;
            else if (v==0)
                n00+=p00;
        }
        else if (a[i]==2){
            if (v==0)
                {printf("0");return 0;}
            if (v==1)
                n01+=p00,n10+=p01;
            else if (v==2)
                n11+=p01,n10+=p11,n01+=p10;
            else if (v==3)
                n11+=p11;
        }
        else if (a[i]==3){
            if (v<2)
                {printf("0");return 0;}
            if (v==2)
                n11+=p01;
            else
                n11+=p11;
        }
    }
    LL ans;
    if (a[n]==0)
        ans=dp[n][0][0];
    else if (a[n]==1)
        ans=dp[n][0][1]+dp[n][1][0];
    else 
        ans=dp[n][1][1];
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-08-15 22:50  zzd233  阅读(169)  评论(0编辑  收藏  举报