前言:
所谓的模拟题,运用的“模拟算法”,其实并没有什么完全准确的定义。模拟算法,用一句老话说,就是“照着葫芦画瓢”;官方化的诠释则是:根据题目表述进行筛选提取关键要素,按需求书写代码解决实际问题。
模拟这个算法其实并不难,主要是逻辑上的麻烦,但正常刷题时我们都不把模拟的逻辑思维理清就直接做,如果这题没有太水的话,是非常容易错的。
核心操作:应该边阅读边将有关的条件一条条地记录下来,阅读完成后要反复核对,先在草稿纸上将流程模拟一遍再动手写代码!!千万别贪快!!
P1042 [NOIP2003 普及组] 乒乓球 - 细节
输入输出样例
输入
WWWWWWWWWWWWWWWWWWWW
WWLWE
输出
11:0
11:0
1:1
21:0
2:1
说明/提示
每行至多 25 个字母,最多有 2500 行。
(注:事实上有一个测试点有 2501 行数据。)
坑点 细节点:
- 玩过乒乓球大部分人都知道,正规乒乓球比赛,不仅分数要大于11(或21),两者分数相差也要大于2。如果比赛分数达到11-10,比赛会继续。直到一个人比另外一个人多两分。(如13-11)
- 没有最后一局也要输出,即0:0情况也要输出;
- 字符数组大小(最坏情况25*2501),至少开char s[62525];
AC代码:(分快,好写不易错)
#include<bits/stdc++.h>
using namespace std;
int a,b;
char ch;
char s[100100];
int count=0;
int main()
{
for(int i=0;;i++)
{
cin>>s[i];
if(s[i]=='E') break; //输入要带‘E’
}
for(int i=0;s[i]!='\0';i++)
{
if(s[i]=='W') a++;
if(s[i]=='L') b++;
if((a>=11||b>=11)&&abs(a-b)>=2||s[i]=='E') //规则的完全模拟
{
cout<<a<<":"<<b<<endl;
a=b=0;
}
}
cout<<endl;
for(int i=0;s[i]!='\0';i++)
{
if(s[i]=='W') a++;
if(s[i]=='L') b++;
if((a>=21||b>=21)&&abs(a-b)>=2||s[i]=='E') //分块一步步来,不易错
{
cout<<a<<":"<<b<<endl;
a=b=0;
}
}
return 0;
}
总结:把题目细节记在草稿纸上,稳才是真的快;
(突然想起一个广告语:跑得快的不一定赢,不跌跟头才是成功。)
P2670 [NOIP2015 普及组] 扫雷游戏 - 规则
细节在于: 从第1行开始,第0行留位置给边角来“顺时针相加”,否则越界;
#include<bits/stdc++.h>
using namespace std;
char a[110][110];
int n,m;
char ch;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>ch;
if(ch=='*') a[i][j]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1) cout<<"*";
else cout<<a[i-1][j]+a[i-1][j+1]+
a[i][j+1]+a[i+1][j+1]+
a[i+1][j]+a[i+1][j-1]+
a[i][j-1]+a[i-1][j-1]; //顺时针加一圈这个数旁边的雷
}
cout<<endl;
}
return 0;
}
P1563 [NOIP2016 提高组] 玩具谜题 - 记录
题目描述
小南有一套可爱的玩具小人, 它们各有不同的职业。
有一天, 这些玩具小人把小南的眼镜藏了起来。 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:
输入输出样例
输入
7 3
0 singer
0 reader
0 mengbier
1 thinker
1 archer
0 writer
1 mogician
0 3
1 1
0 2
输出
writer
输入
10 10
1 C
0 r
0 P
1 d
1 e
1 m
1 t
1 y
1 u
0 V
1 7
1 1
1 4
0 5
0 3
0 1
1 6
1 2
0 8
0 4
输出
y
说明/提示
【样例1说明】
这组数据就是【题目描述】 中提到的例子。
【子任务】
子任务会给出部分测试数据的特点。 如果你在解决题目中遇到了困难, 可以尝试只解决一部分测试数据。
每个测试点的数据规模及特点如下表:
其中一些简写的列意义如下:
• 全朝内: 若为“√”, 表示该测试点保证所有的玩具小人都朝向圈内;
全左数:若为“√”,表示该测试点保证所有的指令都向左数,即对任意的
1 ≤ z ≤ m, a_i=0;
s= 1s=1:若为“√”,表示该测试点保证所有的指令都只数1个,即对任意的
1 ≤ z ≤ m , s_i=1;
职业长度为1 :若为“√”,表示该测试点保证所有玩具小人的职业一定是一个
长度为1的字符串。
思路:
题目可以说的比较长的了,以为是一道控分难题;但是如果边读题目边记录,发现是一道水题 ,真就完完全全的照着葫芦画瓢
朝外(1),左(0):逆时针,+
朝外(1),右(1):顺时针,-
朝内(0),左(0):顺时针,-
朝内(0),右(1):逆时针,+
纯模拟:
#include<bits/stdc++.h>
using namespace std;
int n,m,k=1;
char s[100010][11];
int a[100010];
int x,y;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i]>>s[i];
for(int i=1;i<=m;i++)
{
cin>>x>>y;
if(a[k]==0)
{
if(x==0) k-=y;
else k+=y;
}
else
{
if(x==0) k+=y;
else k-=y;
}
if(k>n) k-=n;
if(k<=0) k+=n;
}
cout<<s[k];
return 0;
}