0
点赞
收藏
分享

微信扫一扫

算法 - 模拟

婉殇成长笔记 2022-03-11 阅读 59
算法p2pc++

前言:

        所谓的模拟题,运用的“模拟算法”,其实并没有什么完全准确的定义。模拟算法,用一句老话说,就是“照着葫芦画瓢”;官方化的诠释则是:根据题目表述进行筛选提取关键要素,按需求书写代码解决实际问题。

模拟这个算法其实并不难,主要是逻辑上的麻烦,但正常刷题时我们都不把模拟的逻辑思维理清就直接做,如果这题没有太水的话,是非常容易错的。

核心操作:应该边阅读边将有关的条件一条条地记录下来,阅读完成后要反复核对,先在草稿纸上将流程模拟一遍再动手写代码!!千万别贪快!!

P1042 [NOIP2003 普及组] 乒乓球 - 细节

输入输出样例

输入 

WWWWWWWWWWWWWWWWWWWW
WWLWE

输出 

11:0
11:0
1:1

21:0
2:1

说明/提示

每行至多 25 个字母,最多有 2500 行。

(注:事实上有一个测试点有 2501 行数据。)

 

坑点 细节点:

  1. 玩过乒乓球大部分人都知道,正规乒乓球比赛,不仅分数要大于11(或21),两者分数相差也要大于2。如果比赛分数达到11-10,比赛会继续。直到一个人比另外一个人多两分。(如13-11)
  2. 没有最后一局也要输出,即0:0情况也要输出;
  3. 字符数组大小(最坏情况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;
}

 

 

举报

相关推荐

0 条评论