NC20241 [SCOI2005]扫雷MINE
题目
题目描述
相信大家都玩过扫雷的游戏。那是在一个 \(n \times m\) 的矩阵里面有一些雷,要你根据一些信息找出雷来。
万圣节到了 ,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字 表示和它 \(8\)连通的格子里面雷的数目。
现在棋盘是 \(n \times 2\)的,第一列里面某些格子是雷,而第二列没有雷,如下图: 由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。
输入描述
第一行为 \(N\),第二行有 \(N\) 个数,依次为第二列的格子中的数。(\(1 ≤ N ≤ 10000\))
输出描述
一个数,即第一列中雷的摆放方案数。
示例1
输入
2
1 1
输出
2
题解
知识点:枚举,递推。
注意到只有两列一列无雷,一列有雷,不妨假设 \(a\) 列无雷,\(b\) 列有雷,\(b[i]\) 为1则 \(i\) 处有雷;\(b[i]\) 为0则 \(i\) 处无雷 。
不妨假设 \(b[1] = 1\) ,就可以通过 \(a[1]\) 确定 \(b[2]\),之后遍历 \([1,n-1]\) 通过 \(a[i] - b[i-1] - b[i]\) 得到 \(b[i+1]\) 。
如果某次 \(b[i+1]<0\) 或者 \(b[i+1] >1\) 或者 \(b[n] + b[n-1] != a[n]\) ,说明这种可能不可行,否则就完成了一种可能。
同理 \(b[1] = 0\) 情况模拟一次,累加可能数即可得到最后答案。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[100007];
bool b[100007];
bool check(int n){
for(int i = 1;i<=n-1;i++){///最后一个点是确定的不需要再遍历,直接最后判断
int tmp = a[i] - b[i] - b[i-1];///当前a的某点还要的雷
if(tmp<0 || tmp>1) return 0;
else b[i+1] = tmp;
}
if(b[n]+b[n-1] == a[n]) return 1;
else return 0;
}
int main()
{
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i = 1; i<=n; i++)
{
cin>>a[i];
}
int ans = 0;
b[1] = 0;
if(check(n)) ans++;
b[1] = 1;
if(check(n)) ans++;
cout<<ans<<'\n';
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16249865.html

浙公网安备 33010602011771号