题目
相信大家都玩过扫雷的游戏。那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来。
万圣节到了 ,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字 表示和它8连通的格子里面雷的数目。
现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷,如下图: 由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。
- 大意:固定N*2的扫雷游戏,且第二列没有雷,固定第二列数字,确定第一列雷的排布方案数
- 思路:容易发现,将第一行第一列的状态(放雷或不放雷)固定之后,根据第一行第二列的数字即可确认下一行第一列是否要放雷,以此类推,下一行是否放雷已经被上一行确定了,即确定了第一行第一列的状态,整个N*2的放雷情况都可以确定。
- 遇到的问题:雷的排布是否满足扫雷规则,不满足规则的各个情况没有弄清楚。
一开始,我只想到了等于右侧第二列数值时,下一行不放雷;大于右侧数值则表示不满足扫雷规则;小于右侧数值则下一行放雷。在最后用右侧数值判断这个排布方案是否可行,等于右侧数值即为一种方案。
之后我尝试了 1 1 2 1 1 这组数据,并逐步输出放雷的情况,发现到有一步,右侧数值比左侧总值大了2(也就是需要放两个雷),因此,得出当小于右侧数值这种情况出现时,有两种情况,右侧数值比左侧总值相差了1,则下一行放雷;右侧数值比左侧总值相差了2,则说明这种放雷的方案出错了。 - 代码处理:在数组中,我使用1表示在这里放雷,0表示不放雷。然后上文提到的左侧总值,就是第二列的数值所“管理”到的三个数组元素的和。
#include<bits/stdc++.h> using namespace std; int ans; int a[10010][4]; int main(){ int n; cin >> n; for(int i = 1; i <= n; i++){ cin >> a[i][2]; } for(int i = 0; i <= 1; i++){ for(int j = 0; j <= n + 10; j++){//进行第二种情况前,需要把“第一列”的值重新置为0 a[j][1] = 0; } a[1][1] = i;//两种情况,“第一行第一列”放雷与不放雷 for(int j = 1; j <= n; j++){ int sum = 0; for(int k = j - 1; k <= j + 1; k++){//计算“左侧总值” sum += a[k][1]; } if((j == n) && (sum == a[j][2])){ ans++; } if(a[j][2] - sum == 1){ a[j + 1][1] = 1; }else if(a[j][2] - sum > 1) { break; }else if(sum == a[j][2]) { a[j + 1][1] = 0; }else{ break; } } } cout << ans; return 0; }



京公网安备 11010502036488号