模拟:扫雷游戏和大炮打蚊子

        最近在学习模拟类题型,通过洛谷出品的一本图书《深入浅出 程序设计竞赛》来学习。(PS:这是本蒟蒻第一次写CSDN,写的很拉跨还请大家将就看)

        顾名思义,“模拟”就是模拟题目的意思一步一步地写下去,是我们在学习任何一门高级语言中的第一个算法,也是一个最简单的算法。 一般情况下,模拟算法的算法复杂度会更高一些,程序也会更复杂,所以有许多题目虽然可以用模拟算法,但是因为时空限制不足等问题导致只能用其他算法来进行优化。 使用方法 模拟算法只要根据题意进行模拟即可。

        在这本书中,模拟章节以扫雷游戏为例,进行了介绍。以下代码来自这本图书,从中我们可以得到一些启示。

        可以看到,教材利用dx和dy两个数组,包含了一个位置8个方向相邻坐标的变换,只有有一个点(i,j)的坐标,让其分别加上(dx,dy)就可以得到这8个新坐标。但是我们不能不忽略一个问题,那就是边界问题,边界上的数据可能会因为不对其进行特殊处理而导致数组越界的问题,然而教程中的处理完美解决了这个问题。

        虽然没有加上“虚拟边框”,但是可以发现,教程在输入数组的时候,下标直接从1开始,这样就自带了一圈虚拟边框,因为我们最终也只是看有数据的这n*m区域,所以这个处理方便地解决了边界的问题。之后再利用循环分别对数据进行判断,判断它是否是“*”(雷),若是雷,直接输出,若不是,就引入cnt这个整型,判断其周围8个位置是否是雷,有一个数据是雷,cnt就加一,最后输出这个数周围的雷数。可以看到,在判断周围8个位置的时候,之前提前准备的dx和dy数组起了大作用,整个程序简洁方便。

        受这个题的启发,我想到了最近不会做的一个题目“大炮打蚊子”,在学习了这个扫雷游戏的程序后,发现这个问题也迎刃而解。

        可以看到,这个题目也存在边界问题和判断周围位置的问题,因此我利用了在这个扫雷游戏例题中出现的技巧,下面是我写出的代码:

#include "stdio.h"
#include "iostream"
#define N 30
using namespace std;
const int dx[] = { 1,0,-1,0 };
const int dy[] = { 0,1,0,-1 };//这四个变化量表示大炮落点周围四个坐标的变化情况
int main()
{
    int m, n, x, y;
    char a1, a2, a3;//定义几个用来吞回车的字符
    cin >> m >> n;
    char a[N][N];
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            cin >> a[i][j];
    a1 = getchar();//这几个都是用来吞回车的
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            if (a[i][j] == '#')
                a[i][j] = '2';//为方便判断,把所有井号换成2
    int t; cin >> t;
    a2 = getchar();
    while (t--)
    {
        cin >> x >> y;
        a3 = getchar();
        x += 1; y += 1;//这个题目数组从0开始算,但是我们从1开始,因此xy都加1抵消这个影响
        int p; p = 0;//用p来存储大炮打死蚊子的数量
        if (a[x][y] == '2' || a[x][y] == '1')
        {
            p++; a[x][y] = '0';
        }
        for (int k = 0; k < 4; k++)//这个循环便是借鉴了扫雷游戏中出现的技巧
        {
            if (a[x + dx[k]][y + dy[k]] == '1')
            {
                p++; a[x + dx[k]][y + dy[k]] = '0';
            }
            if (a[x + dx[k]][y + dy[k]] == '2')
            {
                a[x + dx[k]][y + dy[k]] = '1';
            }
        }
        cout << p << endl;
    }
    return 0;
}

        在这个题目中,炮弹落点位置周围只有上下左右4个位置会被波及,所以定义dx和dy时,只需要4个变化情况即可。之后要注意的是,这个题目给出的炮弹坐标相当于数组下标从0开始计算的,而我们是从1开始计算的,因此我们在得到x和y的值时,要让它们自增1,来抵消这个影响。最后我们把每个炮弹打死的蚊子数量输出即可。

        第一次写CSDN,非常粗糙,感谢大家阅读。希望以后我还可以更多地学习相关知识,给大家分享更多技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值