程序设计竞赛基本算法—模拟

  • 程序设计
  • 基本算法
  • 模拟
万子德·中国科学院大学
2016-02-23
阅读数2730

引言



不知道大家看过双簧没有,双簧是曲艺的一种,一人表演动作,一人藏在身后说或唱,互相配合。身后的人说什么,前面的人表演什么,那么双簧和我们要学习的模拟什么关系呢?我们今天要学习的模拟,就像双簧一样,题目说什么,我们根据题目要求做什么。



基本讲解



模拟题算是相对简单的一些题目,就是说按照题目描述的要求,一步一步来做即可。模拟题对于编程初学者来说,基本考查的就是代码实现能力和打字能力,并不涉及一些太难的算法,这类题目基本不需要太多的思考,不过有的模拟题也会出的很麻烦,比赛过程中如果遇到简单模拟题,基本属于签到题。



例题



例题1hdu2816



【题目大意】




  1. 给出一个字符串,例如:4194418141634192622374,

  2. 两两一组:41 94 41 81 41 63 41 92 62 23 74,每组分别对应手机上的九宫格按键:GZGTGOGXNCS

  3. 通过将电脑键盘的26字母键顺序替换为英文字母顺序QWERTYUIOPASDFGHJKLZXCVBNM = ABCDEFGHIJKLMNOPQRSTUVWXYZ,将上一步的GZGTGOGXNCS替换成OTOEOIOUYVL

  4. 再将OTOEOIOUYVL分成2组: OTOEOI 和 OUYVL,然后再结合成OOTUOYEVOLI

  5. OOTUOYEVOLI翻转,将字符串变成 I LOVE YOU TOO输出





【测试样例】



输入



4194418141634192622374



41944181416341926223



输出



ILOVEYOUTOO



VOYEUOOTIO



【代码】



题目已经给出解题过程,并无难点,关键就看代码如何实现了。




#include
#include

const char raw[12][6] = {{""}, {"ABC"}, {"DEF"}, {"GHI"}, {"JKL"}, {"MNO"},
{"PQRS"}, {"TUV"}, {"WXYZ"}};
const char sam1[] = "QWERTYUIOPASDFGHJKLZXCVBNM";
const char sam2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int maxn = 1010;

char buf[maxn], str[maxn], str2[maxn];
int len;

char f(char ch) {
int i = 0;
for (i = 0; i < 26; ++i)
if (sam1[i] == ch)
return sam2[i];
}

int main() {
int i, j, a, b, aa;
while (scanf("%s", buf) == 1) {
len = strlen(buf);
for (i = j = 0; i < len; i += 2) {
str[j++] = raw[buf[i] - '0' - 1][buf[i+1] - '0' - 1];
}
str[len = j] = '\0';
// puts(str);

for (i = 0; i < len; ++i)
str[i] = f(str[i]);
// puts(str);

a = i = 0;
b = (len + 1) / 2;
aa = b;

while (a < aa && b < len) {
str2[i++] = str[a++];
str2[i++] = str[b++];
}
if (a < aa)
str2[i++] = str[a++];
str2[i] = '\0';
for (--i; i >= 0; --i)
putchar(str2[i]);
puts("");
}
return 0;
}


例题2hdu1276



【题目描述】



某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。



Input



本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。



Output



共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。



Sample Input: 2    20   40



Sample Output:



1 7 19



1 19 37



【解题思路】



模拟过程,把出队列的标记。最后遍历输出没有标记的。



【代码】




#include
#include
#include
#include
#define MAXN 5000+100
using namespace std;
bool vis[MAXN];
int main()
{
int t, N;
bool mark;//标记本次是按二报数 还是按三报数
scanf("%d", &t);
while(t--)
{
scanf("%d", &N);
int num = N;//用num表示人数
mark = true;//按二
memset(vis, false, sizeof(vis));
while(num > 3)
{
int k = 0;
for(int i = 1; i <= N; i++)
{
if(vis[i]) continue;
k++;//累计当前报了多少
if(k == 2 && mark)//当前是按二报数的
{
vis[i] = true;//出队列的标记
num--; k = 0;//总人数减一 k初始化
}
if(k == 3 && !mark)
{
vis[i] = true;
num--; k = 0;
}
}
mark = !mark;//下一次取反
}
for(int i = 1; i <= N; i++)
{
if(!vis[i])
{
if(i > 1) printf(" ");
printf("%d", i);
}
}
printf("\n");
}
return 0;
}


回顾总结



模拟题只需要根据题目写出相应的代码即可,按照题目的要求一步一步实现问题,在此过程中一般不会涉及到较难的算法,当然,模拟题里面也会有很多题目代码实现起来比较麻烦的,因此模拟重在考查编码能力。



例题推荐



Hdu:1302、1035、3456

别默默的看了,快来和大家聊聊吧,登录后回答问题~ 登录 立即注册
赛氪APP全新升级

下载赛氪APP

参加有趣活动,获得赛程提醒

分享大学生活,获得前辈指点

意见反馈

产品建议、功能吐槽、使用问题…

欢迎提出关于赛氪网的问题和建议 :)

微信公众号
关注赛氪订阅号
微信服务号
关注赛氪服务号
温馨提示

非常抱歉!本站不支持旧版本IE浏览器~~建议使用IE10/IE11/Chrome/Firefox/Safari等高级浏览器浏览。

温馨提示
温馨提示
帮助与反馈

热门问题