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

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

引言



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



基本讲解



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



例题



例题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

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

下载赛氪APP

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

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

意见反馈

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

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

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

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

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

热门问题