模拟
模拟,是按照题目的意思将整个过程用代码一步步实现出来。
模拟算法就是按照题目的要求或者情境的设定完整实现其描述过程的方法。
1.它虽然在思维上没有太高的要求,但是对于一些复杂的过程,选择实现的方法从而形成一段代码简洁而运行高效的算法,很考验程序员的基本功和经验积累。
2.模拟题目通常具有码量大、操作多、思路繁复的特点。由于它码量大,经常会出现难以查错的情况,如果在考试中写错是相当浪费时间的。
技巧
1.首先想清楚,在草稿纸上写好实现的流程,写代码的时候一定要思路清晰。
2.在代码中,尽量模块化,写成函数、结构体或类。
3.若要调试,分模块调试。
看道题体验一下
这里给出两种解法
解法一
用数组先存数据,再处理。有的题数据量过多可能不行。
#include <bits/stdc++.h>
using namespace std;
char a[99999];
int k,i=0;
void f(int t,int base)
{
int hua=0,dui=0;
k=t;
for(int j=k;hua<base&&dui<base;j++)
{
if(a[j]=='W')
{
hua++;
t++;
}
else if(a[j]=='L')
{
dui++;
t++;
}
else if(a[j]=='E')
{
cout<<hua<<':'<<dui<<endl;
return;
}
}
if(abs(hua-dui)>=2)
{
cout<<hua<<':'<<dui<<endl;
f(t,base);
}
else
{
while(!(abs(hua-dui)>=2))
{
//t++;
if(a[t]=='W')
{
hua++;
t++;
}
else if(a[t]=='L')
{
dui++;
t++;
}
else if(a[t]=='E')
{
cout<<hua<<':'<<dui<<endl;
return;
}
}
cout<<hua<<':'<<dui<<endl;
f(t,base);
}
}
int main()
{
char c;
while((c=getchar())!='E')
{
if(c!='\n')
{
a[i]=c;
i++;
}
}
a[i]='E';
f(0,11);
cout<<'\n';
f(0,21);
return 0;
}
解法二
边读数据边处理,不用担心数据量到底有多少。
#include <bits/stdc++.h>
using namespace std;
int hua11=0,hua21=0,dui11=0,dui21=0,k=0;
int h21[99999],d21[99999];
void f(char c)
{
if(c=='W')
{
hua11++;
hua21++;
}
else if(c=='L')
{
dui11++;
dui21++;
}
else if(c=='E')
{
cout<<hua11<<':'<<dui11<<endl;
h21[k]=hua21,d21[k]=dui21;
}
if((hua11>=11||dui11>=11)&&abs(hua11-dui11)>=2)
{
cout<<hua11<<':'<<dui11<<endl;
hua11=0,dui11=0;
}
if((hua21>=21||dui21>=21)&&abs(hua21-dui21)>=2)
{
h21[k]=hua21,d21[k]=dui21;
hua21=0,dui21=0;
k++;
}
}
int main()
{
char c;
while((c=getchar())!=NULL)
{
if(c!='\n')
{
f(c);
}
if(c=='E')
break;
}
cout<<'\n';
for(int i=0;i<=k;i++)
cout<<h21[i]<<':'<<d21[i]<<'\n';
return 0;
}
*数组与函数
把数组看作是函数,下标为自变量,对应存的东西为因变量!
并且,由此生出数组的复合,用复合函数的想法来理解,并可结合定义域、值域及映射概念来画图理解。
如a[i]=" "定义了一个由i(定义域)到a[i] (或者说到其存的东西“ ”)的一个映射a;
如a[]=b[c[i]]或b[c[i]],定义了一个由i经c映射和b映射到b[]值域的映射a,或直接写成b[c[i]],注意c,b的先后关系,当然这要求c[]是int 型的;
如a[b[i]]=c[i],定义了一个由把b[]作为定义域到把c[]作为值域的一个映射a,其借由中间自变量(参数)i和中间映射关系b、c来建立上述一一对应的映射a,当然这要求b[]是int 型的;
以此类推······
其实“=”左边第一个[ ]内整体为自变量(定义域),"="右边第一个[ ]对应的值(域)为因变量(值域)。
关系复杂或想不清楚时画映射图!
看道题
奶牛跳舞(The Bovine Shuffle)
题目描述
农夫约翰深信快乐的奶牛会产出更多的牛奶,于是在他的谷仓里安装了一个巨大的迪斯科球,并计划教他的奶牛跳舞!
农夫约翰决定教他的牛跳“牛舞”。一开始他的N头奶牛(1≤N≤100)按一定顺序排成一排,然后进行3次“洗牌”,洗牌以后奶牛变成不同的顺序排列。为了让他的奶牛更容易找到自己的位置,农夫John用位置1…N标记了他的奶牛线的位置,所以队列中的第一头奶牛将在位置1,下一头奶牛将在位置2,以此类推,直到位置N。
洗牌的规则用N个数字a1…aN来描述,在洗牌过程中,处于i位置的奶牛移动到ai位置(因此,每个ai都在1…N的范围内)。在洗牌过程中,每头牛都会移动到它的新位置。幸运的是,所有的ai都是不同的,所以在洗牌时没有两头奶牛试图移动到相同的位置。
农民约翰的奶牛都被分配了不同的7位整数ID号。如果你在三次洗牌后被告知奶牛的顺序,请确定它们最初的顺序。
输入
第一行输入包含N,即奶牛的数量。
下一行包含N个整数a1…aN。
最后一行包含经过三次洗牌后的N头牛的顺序,每头牛由其ID号指定。
输出
N行输出,每行使用一个奶牛ID,按照在三次洗牌之前的顺序输出。
样例输入
5
1 3 4 5 2
1234567 2222222 3333333 4444444 5555555
样例输出
1234567
5555555
2222222
3333333
4444444
应用上面介绍的思想,有如下代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n+1],b[n+1];
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
//int c[n];
for(int i=1;i<=n;i++)
cout<<b[a[a[a[i]]]]<<endl;
return 0;
}
注意循环是必须从1开始,为什么?
因为数组对应的值从1始,为保证对应关系的正确性,数组下标必须从1开始!