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

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

引言

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

基本讲解

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

例题

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

别默默的看了,快来和大家聊聊吧,登录后回答问题~ 登录 立即注册
温馨提示

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

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

热门问题

0
在线咨询