模拟算法题练习(一)

2024-03-01 16:36:46 浏览数 (1)

模拟算法介绍:

模拟算法通过模拟实际情况来解决问题,一般容易理解但是实现起来比较复杂,有很多需要注意的细节,或者是一些所谓很“麻模“的东西。

模拟题一般不涉及太难的算法,一般就是由较多的简单但是不好处理的部分组成的,考察选手的细心程度和整体思维逻辑。

一般为了使得模拟题写的逻辑清晰一些,经常会写比较多的小函数来帮助解题,例如int和string的相互转换、回文串的判断日期的转换、各种特殊条件的判断等等。

(一、扫雷)

用户登录

题目描述 在一个 n 行 m 列的方格图上有一些位置有地雷,另外一些位置为空。请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷 输入描述 输入的第一行包含两个整数 n,m。 第 2 行到第 n 1行每行包含 m 个整数,相邻整数之间用一个空格分隔。如果对应的整数为 0,表示这一格没有地雷。如果对应的整数为 1,表示这格有地雷。 其中,1 <= n,m <= 100 分钟后还是在当天 输出描述 输出 n 行,每行 m 个整数,相邻整数之间用空格分隔。 对于没有地雷的方格,输出这格周围的地雷数量。对于有地雷的方格,输出9。

输入输出样例

输入

3 4 0 1 0 0 1 0 1 0 0 0 1 0

输出

2 9 2 1 9 4 9 2 1 3 9 2

思路:

首先开辟两个二维数组mp和ans,mp用二维数组接收输入样例,ans来确定是否是雷或确定雷的数量。遍历整个数组,判断是否是雷(if(mp[i][j] == 1)),如果是,则ans=9;如果不是,遍历周围周围八格是否有雷(if(mp[_i])[_j] == 1),如果是则ans ;

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;
const int N = 110;
int mp[N][N], ans[N][N];

int main()
{
  int n,m ;cin >> n >> m;
  for(int i = 1; i <= n; i  )
  {
    for(int j = 1; j <= m; j  )
    {
      cin >> mp[i][j];
    }
  }
  for(int i = 1; i <= n; i  )
  {
    for(int j = 1; j <= m; j  )
    {
      if(mp[i][j] == 1)
      {
        ans[i][j] = 9;
      }
      else{
        //遍历周围八格是否有雷,有雷则ans  
        for(int _i = max(1, i - 1); _i <= min(n, i   1);   _i)
      {
        for(int _j = max(1, j - 1); _j <= min(m, j   1);   _j)
        {
          if(mp[_i][_j]) ans[i][j]  ;
        }
      }
      }
    }
  }
  for(int i = 1; i <= n;   i)
  {
    for(int j = 1; j <= m;   j)
    {
      cout << ans[i][j] << ' ';
    }
    cout << 'n';
  }

  return 0;
}

(二、灌溉)

用户登录

题目描述 小蓝负责花园的灌溉工作。 花园可以看成一个n 行 m 列的方格图形。中间有一部分位置上安装有出水管。 小蓝可以控制一个按钮同时打开所有的出水管,打开时,有出水管的位置可以被认为已经灌溉好。 每经过一分钟,水就会向四面扩展一个方格,被扩展到的方格可以被认为已经灌溉好。即如果前一分钟某一个方格被灌溉好,则下一分钟它上下左右的四个方格也被灌溉好。 给定花园水管的位置,请问 k分钟后,有多少个方格被灌溉好? 输入描述 输入的第一行包含两个整数 n,m。 第二行包含一个整数 t,表示出水管的数量。 接下来t行描述出水管的位置,其中第之行包含两个数 r,c表示第,行第 c列有一个排水管。 接下来一行包含一个整数 k。 其中,1<= n,m<= 100,1<=t<= 10,1<=k<= 100。 输出描述 输出一个整数,表示答案。

输入输出示例

输入:

3 6 2 2 2 3 4 1

输出:

9

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;
const int N = 110;
int a[N][N], b[N][N];

int main()
{
    int n, m; cin >> n >> m;
    int t; cin >> t;
    while (t--)
    {
        int x, y; cin >> x >> y;
        a[x][y] = 1;
    }
    int k; cin >> k;
    while (k--)
    {
        for (int i = 1; i <= n;   i)
        {
            for (int j = 1; j <= m;   j)
            {
                if (a[i][j])
                {
                    if (a[i][j])b[i][j] = b[i - 1][j] = b[i   1][j] = b[i][j - 1] = b[i][j   1] = 1;
                }
            }
        }
    }
    //将b复制回a
    for (int i = 1; i <= n;   i)
    {
        for (int j = 1; j <= m;   j)
        {
            a[i][j] = b[i][j];
        }
    }
    int count;
    for (int i = 1; i <= n;   i)
    {
        for (int j = 1; j <= m;   j)
        {
            if (a[i][j] == 1)
                count  ;
        }
    }
    cout << count;
    return 0;
}

(三、回文日期)

用户登录

题目描述 2020 年春节期间,有一个特殊的日期引起了大家的注意:2020年2月2日。因为如果将这个日期按“yyyymmdd”的格式写成一个8位数是20200202,恰好是一个回文数。我们称这样的日期是回文日期。 有人表示 20200202 是“千年一遇”的特殊日子。对此小明很不认同,因为不到2年之后就是下一个回文日期:20211202即2021年12月2日。 也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA型的回文日期。对此小明也不认同,因为大约 100年后就能遇到下一个ABABBABA型的回文日期:21211212即2121年12月12日。算不上“千年一遇”, 顶多算“千年两遇”。 给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。 输入描述 输入包含一个八位整数 N,表示日期。 对于所有评测用例,10000101<N<89991231,保证 N 是一个合法日期的 8 位数表示。 输出描述 输出两行,每行1个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。

输入输出样例:

输入:

20200202

输出

20211202 21211212

有一说一这题大佬的题解是真的强

编写这么几个函数:

1、从int转换为指定位数的string的函数 2、从string转换为int的函数 3、判断闰年的函数 4、判断日期是否合法的函数 5、判断字符串是否是回文的函数 6、判断字符串是否是ABABBABA型回文的函数

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;

// 将字符串转换为数字
int s2i(string s)
{
	int res = 0;
	for (const auto& i : s)res = res * 10   i - '0';// 通过字符与'0'的差值来得到对应的数字,并累加到结果中 
	return res;
}

// 将整数转换为指定宽度的字符串 
string i2s(int x, int w)
//   要被转换的整数, 转换的位数
{
	string res;
	while (x)res  = (x % 10)   '0', x /= 10;// 取x的个位数,并转换为字符,添加到结果字符串中,然后x除以10 
	while (res.length() < w)res  = '0';// 当结果字符串的长度小于指定的位数时,循环执行
	reverse(res.begin(), res.end());
	return res;
}

// 判断是否为闰年  
bool isLeapYear(int year)
{
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// 判断日期是否合法
bool isok(int year, int month, int day)
{
	int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (isLeapYear(year))days[2] = 29;//闰年2月29天
	return day <= days[month];
}

// 判断是否为回文
bool isPa(string s)
{
	for (int i = 0; i < s.length() / 2;   i)
	{
		if (s[i] != s[s.length() - 1 - i])return false;
		 如果前后字符不相等,则不是回文  
	}
	return true;
}

//判断是否是ABBA型回文
bool isPa2(string s)
{
	if (isPa(s))return false;
	return s[0] == s[2] && s[1] == s[3];
}


int main()
{
	string s; cin >> s;
	int year = s2i(s.substr(0, 4)), month = s2i(s.substr(4, 2)), day = s2i(s.substr(6, 2));
	// 分割字符串为对应的年, 月, 日

	bool ans1 = false, ans2 = false;// 定义两个标志变量,用于标记是否找到了回文和ABBA型日期  

	for (int i = year; i <= 9999;   i)//遍历年份
	{
		for (int j = 1; j <= 12;   j)//遍历月份
		{
			if (i == year && j < month)continue;
			// 如果是是当前年份且月份小于输入的月份,则跳过  
			for (int k = 1; k <= 31;   k)//遍历天数
			{
				if (i == year && j == month && k <= day)continue;
				// 如果是当前年份且是当前月份且日小于等于输入的日,则跳过 

				if (!isok(i, j, k))continue;
				// 如果不合法,则跳过

				string date = i2s(i, 4)   i2s(j, 2)   i2s(k, 2);
				// 如果还没有找到回文日期且当前日期是回文,则输出并标记已找到
				if (!ans1 && isPa(date))
				{
					cout << date << 'n';
					ans1 = true;
				}
				// 如果还没有找到ABBA型日期且当前日期是ABBA型,则输出并标记已找到
				if (!ans2 && isPa2(date))
				{
					cout << date << 'n';
					ans2 = true;
				}
			}
		}
	}
	return 0;
}

今天就先到这了!!!

看到这里了还不给博主扣个: ⛳️ 点赞☀️收藏 ⭐️ 关注!

0 人点赞