模拟算法是一个非常经典的算法,是所有人学习的第一个算法。

模拟,顾名思义,就是题目中给出一个流程,然后你写出一份代码进行模拟,实现这个流程。

它一般是比赛中的签到送分题,但是模拟一定要注意细节,千万要读懂题目中的意思!!!

模拟通常需要一定的代码能力,它码量大,操作多且思路繁琐,需要多多练习。

例题一 洛谷P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布

P1328 [NOIP 2014 提高组] 生活大爆炸版石头剪刀布 - 洛谷

Solution :  

因为 N 十分小,所以我们完全可以考虑模拟 N 次石头剪刀布的结果。

先依据循环节,补齐两个人的全部出拳;

再枚举每一次出拳两人的胜负结果,统计得分,得出答案。

//P1328
#include<bits/stdc++.h>
using namespace std; 
int n,n1,n2,a[210],b[210],x,y;
int main()
{
	//--------读入--------- 
	scanf("%d%d%d",&n,&n1,&n2);
	for(int i=1;i<=n1;i++)
	{
		scanf("%d",&x);
		a[i]=x;
	}
	for(int i=1;i<=n2;i++)
	{
		scanf("%d",&y);
		b[i]=y;
	}
	//---------补齐--------- 
	for(int i=n1+1;i<=n;i++)
	{
		a[i]=a[i-n1];
	}
	for(int i=n2+1;i<=n;i++)
	{
		b[i]=b[i-n2];
	}
	//------判断--------
	x=0,y=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i]==0&&b[i]==0||a[i]==1&&b[i]==1||a[i]==2&&b[i]==2||a[i]==3&&b[i]==3||a[i]==4&&b[i]==4)
		{
			x+=0,y+=0;
		}
		    if(a[i]==0&&b[i]==1)y++;
            if(a[i]==0&&b[i]==2)x++;
            if(a[i]==0&&b[i]==3)x++;
            if(a[i]==0&&b[i]==4)y++;
            if(a[i]==1&&b[i]==0)x++;
            if(a[i]==1&&b[i]==2)y++;
            if(a[i]==1&&b[i]==3)x++;
            if(a[i]==1&&b[i]==4)y++;
            if(a[i]==2&&b[i]==0)y++;
            if(a[i]==2&&b[i]==1)x++;
            if(a[i]==2&&b[i]==3)y++;
            if(a[i]==2&&b[i]==4)x++;
            if(a[i]==3&&b[i]==0)y++;
            if(a[i]==3&&b[i]==1)y++;
            if(a[i]==3&&b[i]==2)x++;
            if(a[i]==3&&b[i]==4)x++;
            if(a[i]==4&&b[i]==0)x++;
            if(a[i]==4&&b[i]==1)x++;
            if(a[i]==4&&b[i]==2)y++;
            if(a[i]==4&&b[i]==3)y++; 
	} 
    printf("%d %d",x,y);
    return 0;
}

例题二 洛谷P11228 [CSP-J 2024] 地图探险

P11228 [CSP-J 2024] 地图探险 - 洛谷

Solution :

我们可以注意到 k 是 1e6 级别的,虽然是多测,但 T 范围只到5,所以复杂度为 O(Tk) 的模拟算法完全可以轻松通过。

所以直接按题目中所说的模拟即可。

注意:多测不清空,挂分两行泪(因为循环清空不彻底,考场代码挂了30分.......)、

//P11228
#include <bits/stdc++.h>
#define int long long
using namespace std;
int T,ans; 
int n,m,k;
int x,y,d;
int a[1005][1005],vis[1005][1005];
char c;
signed main()
{
	scanf("%lld",&T);
	while(T--){
		ans=0;
		scanf("%lld%lld%lld",&n,&m,&k);
		scanf("%lld%lld%lld",&x,&y,&d);
		memset(vis,0,sizeof(vis));
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++){
				cin>>c;
				if(c=='.') a[i][j]=1;
			}
		for(int i=1;i<=k;i++){
			if(vis[x][y]==0) ans++,vis[x][y]=1;
			if(d==0){
				if(a[x][y+1]==1) y++;
				else d=(d+1)%4;
			} 
			else if(d==1){
				if(a[x+1][y]==1) x++;
				else d=(d+1)%4;
			}
			else if(d==2){
				if(a[x][y-1]==1) y--;
				else d=(d+1)%4;
			}
			else if(d==3){
				if(a[x-1][y]==1) x--;
				else d=(d+1)%4;
			}
			if(vis[x][y]==0) ans++,vis[x][y]=1;
			//printf("%lld %lld %lld %lld\n",ans,x,y,d);
		}
		printf("%lld\n",ans);
	}
	return 0; 
}
    Logo

    集算法之大成!助力oier实现梦想!

    更多推荐