1.模拟算法介绍:
- 模拟算法通过模拟实际情况来解决问题,一般容易理解但是实现起来比较复杂,有很多需要注意的细节,或者是一些所谓很“麻烦”的东西。
- 模拟题一般不涉及太难的算法,一般就是由较多的简单但是不好处理的部分组成的,考察选手的细心程度和整体的逻辑思维。
- 一般为了使得模拟题写的逻辑清晰一些,经常会写比较多的小函数来帮助解题,例如int和string的相互转换、回文串的判断、日期的转换、各种特殊条件的判断等等。
2.例题讲解:
题号:lanqiao OJ 549
1.扫雷
该题要考虑边界情况,开设两个数组对a数组扫描,用b数组记录,根据题意一步步写就好,注意扫到雷时将该位置跳过(更为详细的步骤可以看12.题目:编号549 扫雷)
#include<bits/stdc++.h>
using namespace std;
const int N=150;
int a[N][N],b[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>>a[i][j];
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
//有雷变9,该位置则不扫描,跳过
if(a[i][j]){
b[i][j]=9;
continue;
}
//扫描地雷,边界问题用max函数和min函数解决,不需要罗列条件
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(a[_i][_j]){
b[i][j]++;
}
}
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
cout<<b[i][j]<<' ';
}
cout<<'\n';
}
return 0;
}
题号:lanqiao OJ 551
2.灌溉
与上题类似,还是设两个数组对a扫描,用b记录,多了一步将a与b同步,最后输出ans (更为详细的步骤可以看13.题目:编号511 灌溉)
#include<bits/stdc++.h>
using namespace std;
const int N=105;
bool a[N][N],b[N][N];
int main(){
int n,m;
cin>>n>>m;
int t;
cin>>t;
while(t--){
int c,r;
cin>>c>>r;
a[c][r]=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]){
b[i][j]=b[i-1][j]=b[i+1][j]=b[i][j-1]=b[i][j+1]=1;
}
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
a[i][j]=b[i][j];
}
}
}
int ans=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(a[i][j]){
ans++;
}
}
}
cout<<ans<<'\n';
return 0;
}
题号:lanqiao OJ 498
3.回文日期
###该题难在思维,写的时候要保持清醒的头脑,缜密的逻辑,想好达成该目的要有什么操作,一定要自己好好想一想
要编写这么几个函数:
- 从int转换为指定位数的string的函数
- 从string转换为int的函数
- 判断闰年的函数
- 判断日期是否合法的函数
- 判断字符串是否是回文的函数
- 判断字符串是否是ABABBABA型回文的函数
(更为详细的步骤可以看14.题目:编号498 回文日期)
#include<bits/stdc++.h>
using namespace std;
//字符串类型转换为整型函数
int s2i(string x){
int res=0;
for(auto & i : x )res=res*10+i-'0';
return res;
}
//整型转换为字符串类型函数(缺位自动补0)
string i2s(int x,int w){
string res;
while(x){
res+=x%10+'0';
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)||(year%400==0);
}
//判断日期是否合法
bool isok(int year,int month,int day){
int nums[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))nums[2]=29;
return day<=nums[month];
}
//判断是否是回文1
bool isPa1(string s){
for(int i=0;i<s.length()/2;++i){
if(s[i]!=s[s.length()-1-i])return false;
}
return true;
}
//判断是否是回文2
bool isPa2(string s){
if(!isPa1(s))return false;
return s[0]==s[2]&&s[1]==s[3];
}
int main(){
string s;cin>>s;
bool ans1=false,ans2=false;
int year=s2i(s.substr(0,4)),month=s2i(s.substr(4,2)),day=s2i(s.substr(6,2));
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);
//判断1
if(!ans1&&isPa1(date)){
cout<<date<<'\n';
ans1=true;
}
//判断2
if(!ans2&&isPa2(date)){
cout<<date<<'\n';
ans2=true;
}
}
}
}
return 0;
}