题目描述
小Q空的时候挺喜欢玩玩电脑游戏的。自从编程技术提高后,他就想,要是自己也能开发出一款游戏来,那该多好啊!不过,小Q也不着急,先练好基本功再说。Windows中就有一款叫扫雷的小游戏,挺好玩的,不过想编出一个来,还真不容易。小Q就自己设想了一种简单的扫雷游戏:在n行2列的方格棋盘上,左列某些方格内埋有地雷,而右列每个方格中都有一个数字(0~3),第I格的数字表示:左列第I-1、I、I+1格(即:上、中、下三格)中埋雷的总数。如下所示:左图是初始状态,右图是扫雷完成状态(插小旗的方格内有雷)。
你的任务是:根据右列的数字分析出左列格子中的地雷(0表示无雷,1表示有雷),并且统计出左列格子中地雷的总数。
小Q想,如果这样的任务能完成了,相信编出更复杂的扫雷游戏也就为期不远了。
输入
第一行,一个整数N(2≤N≤40),第二行有N个数字(以一个空格相隔),表示右列格子中的数字。输入数据保证正确有解。
输出
第一行是N个0、1数字(没有空格相隔),表示左列每格中有无地雷。第二行一个整数,表示地雷总数。
样例输入
7
1 2 3 2 2 2 2
样例输出
0111011
5
思路分析
本题是一道模拟题
因为根据右列第i个数字,可以得出左列第i,i - 1,i + 1个各自的地雷数,故我们从上向下枚举,只需要知道左列第一个各自有没有雷,即可得到答案,设左列为a数组,右列为b数组,因为如果知道了左列第一个a[1]是否有雷,通过右列第一个b[1]与a[1]、a[2]有关,故可以判断出a[2]是否有雷,b[2]与a[1]、a[2]、a[3]有关,故可以知道a[3]是否有雷,以此类推,即可得到a[1]~a[n]是否有雷
但现在无法通过b[1]判断出a[1]的情况,故我们可以先假设a[1]有雷,然后推断出a[2]~a[n],如果存在矛盾,那么假设错误,从而a[1]没有雷,重新进行一次推理即可得到正确答案
首先假设a[1]有雷,用st来标记是否矛盾,初始为false
// 首先通过b[1]判断出a[1] 和 a[2]
if(b[1] == 0) st = true; // 若b[1]为0,则a[1]和a[2]均为0,则矛盾
else{
a[1] = 1; // 若b[1]不为0,则按照假设,a[1] = 1,即有雷
if(b[1] == 2) a[2] = 1; // 若b[2] = 2,则a[1],a[2]均有雷
else a[2] = 0; // 若b[2] = 1,a[1]和a[2]只有一个雷,即a[1]
}
for(int i = 2;i < n;i++){
int tmp = a[i - 1] + a[i]; // a[i - 1]和a[i]均已被明确判断
if(b[i] - tmp == 1) a[i + 1] = 1;
else if(tmp + 1 < b[i]){ // 如果在a[i - 1],a[i]已确定是否有雷,a[i + 1]有雷的情况下(此情况为b[i]的合法最大值),b[i] > a[i - 1] + a[i] + 1(b[i]大于其合法最大值),则矛盾
st = true;
break;
}
}
如果矛盾,则a[1]没有雷,再相同步骤推导一遍,不过不需要判断是否矛盾了
if(st){
a[1] = 0;
if(b[1] == 1) a[2] = 1;
else a[2] = 0;
for(int i = 2;i < n;i++){
int tmp = a[i - 1] + a[i];
if(b[i] - tmp == 1) a[i + 1] = 1;
}
}
最后输出第i格是否有雷并统计总雷数即可
for(int i = 1;i <= n;i++){
cout << a[i];
res += a[i];
}
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 40 + 10;
int n;
int a[N],b[N];
int res;
bool st;
int main(){
ios::sync_with_stdio;
cin.tie(0),cout.tie(0);
cin >> n;
for(int i = 1;i <= n;i++) cin >> b[i];
// 首先假设a[1]有雷,用st来标记是否矛盾,初始为false
// 首先通过b[1]判断出a[1] 和 a[2]
if(b[1] == 0) st = true; // 若b[1]为0,则a[1]和a[2]均为0,则矛盾
else{
a[1] = 1; // 若b[1]不为0,则按照假设,a[1] = 1,即有雷
if(b[1] == 2) a[2] = 1; // 若b[2] = 2,则a[1],a[2]均有雷
else a[2] = 0; // 若b[2] = 1,a[1]和a[2]只有一个雷,即a[1]
}
for(int i = 2;i < n;i++){
int tmp = a[i - 1] + a[i]; // a[i - 1]和a[i]均已被明确判断
if(b[i] - tmp == 1) a[i + 1] = 1;
else if(tmp + 1 < b[i]){ // 如果在a[i - 1],a[i]已确定是否有雷,a[i + 1]有雷的情况下(此情况为b[i]的合法最大值),b[i] > a[i - 1] + a[i] + 1(b[i]大于其合法最大值),则矛盾
st = true;
break;
}
}
// 如果矛盾,则a[1]没有雷,再相同步骤推导一遍,不过不需要判断是否矛盾了
if(st){
a[1] = 0;
if(b[1] == 1) a[2] = 1;
else a[2] = 0;
for(int i = 2;i < n;i++){
int tmp = a[i - 1] + a[i];
if(b[i] - tmp == 1) a[i + 1] = 1;
}
}
// 最后输出第i格是否有雷并统计总雷数即可
for(int i = 1;i <= n;i++){
cout << a[i];
res += a[i];
}
cout << '\n' << res;
return 0;
}

463

被折叠的 条评论
为什么被折叠?



