bzoj1088 P2327 [SCOI2005]扫雷

P2327 [SCOI2005]扫雷

emmmmm.....这题真可以用状压写

因为每个数字只对3个格子有影响,相当于只有2^3=8种状态,所以可以用状压瞎搞

我们用8个数字代表二进制下的8种状态

0 000 ; 1 001 ; 2 010 ; 3 011 ;

4 100 ; 5 101 ; 6 110 ; 7 111 ;

0/1表示无/有雷

设 f[ i ][ j ]表示在第 i-2 ~ i 个格子的状态为 j 的方案数

状态转移时(设当前状态为 i)相当于 f[ i+1 ][ j ]=f[ i ][ j>>1 ]+f[ i ][ j>>1|1 ] 

但是我懒得写判断所以直接手算可行转移了(逃

注意不能省略 三个格都为0的情况

#include<cstdio>
using namespace std;
int n,f[10002][8];
int main(){
    scanf("%d",&n); int opt;
    scanf("%d",&opt);
    if(opt==1) f[2][1]=f[2][2]=1;
    else if(opt==2) f[2][3]=1;
    else if(opt==0) f[2][0]=1;
    for(int i=2;i<=n;++i){//把数字转二进制自己观察吧qwq
        scanf("%d",&opt);
        if(opt==1){
            f[i+1][1]=f[i][4]+f[i][0];
            f[i+1][2]=f[i][1]+f[i][5];
            f[i+1][4]=f[i][2]+f[i][6];
        }else if(opt==2){
            f[i+1][3]=f[i][1]+f[i][5];
            f[i+1][5]=f[i][2]+f[i][6];
            f[i+1][6]=f[i][3]+f[i][7];
        }else if(opt==3) f[i+1][7]=f[i][3]+f[i][7];
        else f[i+1][0]=f[i][0]+f[i][4];
    }
    printf("%d",f[n+1][0]+f[n+1][2]+f[n+1][4]+f[n+1][6]); //注意第 n+1 个格子必须为0
    return 0;
}

 

posted @ 2018-08-29 11:35  kafuuchino  阅读(...)  评论(... 编辑 收藏