题目:
https://ac.nowcoder.com/acm/problem/20241

  • 万圣节到了 ,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字 表示和它8连通的格子里面雷的数目。
  • 现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷,由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。
  • N <= 1e5

思路:
只要确定了第一列第一格是否有雷的状态,第一列后面的状态可以根据上一行第二列的状态判定。
所以只要判断当第一列第一个有雷情况和无雷情况下方案是否成立(最终可能方案数只有0,1,2)
因此采用枚举。

初始代码————通过率30%

#include<stdio.h>
const int INF = 0x3f3f3f3f;
const int maxn = 1e4+7;
int a[maxn] = {0};  //存储第二列的初始数据
int judge[maxn] = {0};  //储存第一列的数据

int main () {
    //数据初始化
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int ans = 0;
    int temp = a[0];  //temp 动态地存三个数

    //枚举情况一
    //第一列第一格有雷
    int i;
    temp = 1;  
    judge[1] = 1;
    for (i = 1; i <= n; i++) {
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
            temp -= judge[i-1];
        }
        if (a[i] < temp) {
            break;
        }
    }
    if (i > n) {
        ans++;
    }

    memset(judge, 0, sizeof(int)*man
    //枚举情况二
    //第一列第一格无雷
    temp = 0;
    judge[1] = 0;
    for (i = 1; i <= n; i++) {
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
            temp -= judge[i-1];
        }
        if (a[i] < temp) {
            break;
        }
    }
    if (i > n) {
        ans++;
    }

    printf("%d", ans);
}

初始代码的问题及修改方法:

  • 每次 i++,都应该执行 temp -= judge[i-1]; 所以应该放在 if 判断的外面

即把下面的代码片段:

    for (i = 1; i <= n; i++) {
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
            temp -= judge[i-1];
        }
        if (a[i] < temp) {
            break;
        }
    }

修改为:

    for (i = 1; i <= n; i++) {
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
        }
        temp -= judge[i-1];
        if (a[i] < temp) {
            break;
        }
    }

通过率提升到30%

  • 在每次判断 if (a[i] > temp) 后,temp 已经动态存了当前 i 下 a [ i ] 所对应的第一列的三个格 ( i - 1 , i , i + 1 ) 中的雷数(前两个是上一次for循环保存在temp中的,第三个是当前for循环保存在temp中的),应该加上判断语句判断雷数是否符合。
    再次修改上面的代码片段并调整代码顺序:

      for (i = 1; i <= n; i++) {
          if (a[i] < temp) {
              break;
          }      
          if (a[i] > temp) {
              temp += 1;
              judge[i+1] = 1;
          }
          if (a[i] != temp) {
              break;
          }
          temp -= judge[i-1];
    
      }

    通过率提升为90%

  • ans判定的时候加强判断末尾的边界条件
    //注意上面的 for 循环最后出来的时候有 temp -= judge[i-1]; 和 i++;
    AC代码:

#include<stdio.h>
#include<string.h>
const int INF = 0x3f3f3f3f;
const int maxn = 1e4+7;
int a[maxn] = {0};
int judge[maxn] = {0};
int main () {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int ans = 0;
    int temp = a[0];  //temp 动态地存三个数

    //枚举情况一
    //第一列第一格有雷
    int i;
    temp = 1; 
    judge[1] = 1;
    for (i = 1; i <= n; i++) {
        if (a[i] < temp) {
            break;
        }
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
        }
        if (a[i] != temp) {
            break;
    }     
        temp -= judge[i-1];
    }
    //判断此方案是否成立 
    //注意末尾边界条件( temp == judge[i-1])
    if (i > n && temp == judge[i-1]) {
        ans++;
    }

    memset(judge, 0, sizeof(int)*maxn);
    //枚举情况二
    //第一列第一格无雷
    temp = 0;
    judge[1] = 0;
    for (i = 1; i <= n; i++) {
        if (a[i] < temp) {
            break;
        }
        if (a[i] > temp) {
            temp += 1;
            judge[i+1] = 1;
        }
        if (a[i] != temp) {
            break;
    }     
        temp -= judge[i-1];
    }
    if (i > n && temp == judge[i-1]) {
        ans++;
    }

    printf("%d", ans);
}