zoukankan      html  css  js  c++  java
  • 【BZOJ 1088 扫雷Mine】模拟

    http://www.lydsy.com/JudgeOnline/problem.php?id=1088

    2*N的扫雷棋盘,第二列的值a[i]记录第 i 个格子和它8连通的格子里面雷的数目。

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

    设第一列的值为b[i],不难得出以下递推关系

    b[0] + b[1] = a[0]

    b[0] + b[1] + b[2] = a[1]

    ...

    b[i] = a[i-1] - a[i-2] + b[i-3]
    或 b[i] = a[i-1] - b[i-1] - b[i-2]

    由此发现,b[0]、b[1]确定了,后续的b[i]也由递推式唯一的确定了。而又有b[0]+b[1] = a[0]的限制条件,故可根据a[0]的值枚举b[0], b[1]的组合,然后顺次求出b[i], 判断每个b[i]值是否合法,一旦发现不合法,则此种枚举情况不成立。

    程序流程图如下(这里的“合法”判断与具体位置有关,如a[0], a[n-1] <3, a[n-1] == b[n-1] + b[n-2]):

    代码如下(为了直观表达流程图,用了goto语句):

     1 #include <cstdio>
     2 using namespace std;
     3 
     4 int n;
     5 int a[10005];
     6 int b[10005];
     7 
     8 int main()
     9 {
    10     scanf("%d", &n);
    11     for(int i=0; i<n; i++){
    12         scanf("%d", &a[i]);
    13     }
    14     int cnt = 0;
    15 
    16     for(int i=0; i<n; i++){ //非法 
    17         if(a[i]<0 || a[i]>3){
    18             goto L;
    19         }
    20     }
    21     if(a[n-1]==3 || a[0] == 3){ //非法 
    22         goto L;
    23     }
    24     
    25     if(a[0] == 0) b[0] = b[1] = 0;
    26     else if(a[0] == 2) b[0] = b[1] = 1; 
    27     
    28     if(a[0] == 1) goto B;
    29     
    30     b[2] = a[1] - a[0]; //0或2的情况 
    31     if(b[2] < 0 || b[2] > 1){
    32         goto L;
    33     }
    34     for(int i=3; i<n; i++){
    35         b[i] = a[i-1] - a[i-2] + b[i-3];
    36         if(b[i] < 0 || b[i] > 1){
    37             goto L;
    38         }
    39     }
    40     if(b[n-1] + b[n-2] != a[n-1]) //检查最后一个a 
    41         goto L;
    42     printf("1
    ");
    43     return 0;    
    44 
    45 B:    b[0] = 0; b[1] = 1; //01或10的情况 
    46     b[2] = a[1] - a[0];
    47     if(b[2] < 0 || b[2] > 1){
    48         goto L1;
    49     }
    50     for(int i=3; i<n; i++){
    51         b[i] = a[i-1] - a[i-2] + b[i-3];
    52         if(b[i] < 0 || b[i] > 1){
    53             goto L1;
    54         }
    55     }
    56     if(b[n-1] + b[n-2] != a[n-1])
    57         goto L1;
    58     cnt++;
    59         
    60 L1:    b[0] = 1; b[1] = 0; //试探另一种 
    61     b[2] = a[1] - a[0];
    62     if(b[2] < 0 || b[2] > 1){
    63         goto L;
    64     }
    65     for(int i=3; i<n; i++){
    66         b[i] = a[i-1] - a[i-2] + b[i-3];
    67         if(b[i] < 0 || b[i] > 1){
    68             goto L;
    69         }
    70     }
    71     if(b[n-1] + b[n-2] != a[n-1])
    72         goto L;
    73     cnt++;
    74         
    75 L:    printf("%d
    ", cnt);
    76     return 0;
    77 
    78 }
    BZOJ 1088
  • 相关阅读:
    标签的讲解
    属性分类
    LeetCode 003. 无重复字符的最长子串 双指针
    Leetcode 136. 只出现一次的数字 异或性质
    Leetcode 231. 2的幂 数学
    LeetCode 21. 合并两个有序链表
    象棋博弈资源
    acwing 343. 排序 topsort floyd 传播闭包
    Leetcode 945 使数组唯一的最小增量 贪心
    Leetcode 785 判断二分图 BFS 二分染色
  • 原文地址:https://www.cnblogs.com/helenawang/p/5382725.html
Copyright © 2011-2022 走看看