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);//判断1if(!ans1&&isPa1(date)){cout<<date<<'\n';ans1=true;}//判断2if(!ans2&&isPa2(date)){cout<<date<<'\n';ans2=true;}}}}return 0;
}