2012蓝桥杯本科组C/C++决赛题

星期几

【结果填空】 (满分5分)





    1949年的国庆节(10月1日)是星期六。 



    今年(2012)的国庆节是星期一。



    那么,从建国到现在,有几次国庆节正好是星期日呢?





    只要答案,不限手段!

    可以用windows日历,windows计算器,Excel公式,。。。。。

    当然,也可以编程!



    不要求写出具体是哪些年,只要一个数目!

    千万不要提交源代码!



    答案不要写在这里,写在“解答.txt”中
View Code
#include <iostream>

using namespace std;



const int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

const int b[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};



bool leapyear(int y)

{

    //我尼玛这里错了无数次了,天灵灵地灵灵这次一定要记住

    //能被400整除,或者能被4整除但不能被"100"整除 

    if(y % 400 == 0 || (y % 4 == 0 && y % 100 != 0))

        return true;

        

    return false;

}

int main()

{

    int n = 6, day = 0, count = 0;

    for(int m = 10; m <= 12; m++)

    {

        day += a[m];

    }

    //周日~周六 : 0~6 

    n = (n + (day % 7)) % 7;    //0

    

    for(int y = 1950; y <= 2012; y++)

    {

        if(!leapyear(y))    //不是闰年 

        {

            day = 0;

            for(int m = 1; m <= 9; m++)

                day += a[m];

            n = (n + (day % 7)) % 7;    //十月一日星期几

            

            if(n == 0)    

            {

                count++;

                cout << y << endl;

            }

            

            day = 0;

            for(int m = 10; m <= 12; m++)

                day += a[m];

            n = (n + (day % 7)) % 7;    //次年一月一日星期几 

        }

        else    //闰年 

        {

            day = 0;

            for(int m = 1; m <= 9; m++)

                day += b[m];

            n = (n + (day % 7)) % 7;    //十月一日星期几 

            

            if(n == 0)

            {

                count++;

                cout << y << endl;

            }



            day = 0;

            for(int m = 10; m <= 12; m++)

                day += b[m];

            n = (n + (day % 7)) % 7;    //次年一月一日星期几 

        }

    }

    cout << count;



    return 0;

}
View Code

 

数据压缩

【代码填空】(满分16分)



    某工业监控设备不断发回采样数据。每个数据是一个整数(0到1000之间)。各个数据间用空白字符(空格,TAB或回车换行)分隔。这些数据以文本形式被存储在文件中。



    因为大多数时候,相邻的采样间隔数据是相同的,可以利用这个特征做数据的压缩存储。其方法是:对n(n>1)个连续相同的数字只记录n和该数字本身;对m(m>0)个连续不重复的数字,则记录 m*-1 和这些数字本身(之所以用负数,是为了与第一种情况区分,便于解压缩)。



    例如:采样数字:

    12 34 34 25 25 25 25 11 15 17 28 14 22 22 22 13

    则根据上述规则变化后:

    -1 12 2 34 4 25 -5 11 15 17 28 14 3 22 -1 13



    下面的程序实现了这个功能。请仔细阅读分析代码,填写空白的部分。



void pop(int s, int* buf, int c, FILE* fp)

{

    int i;

    if(s)

    {

        fprintf(fp, "%d %d ", c, *buf);

    }

    else

    {

        fprintf(fp, "%d ", -c);

        for(i=0; i<c; i++)

        {

            fprintf(fp, "%d ", buf[i]);

        }

    }

}



void dopack(FILE* r, FILE* w)

{

    int buf[BUF_N];



    int pos = 0;  // 下一个数字在buf中将要存放的位置

    int c = 0;    // 当前段已读入的整数个数

    int pst; 

    int cst;



    while(fscanf(r, "%d", buf+pos)==1)

    {

        if(c==0)

        {

            c = pos = 1;

            continue;

        }



        if(c==1)

        {

            pst = buf[0] == buf[1];

            pos = pos + 1 - pst;

            c = 2;

            continue;

        }

        

        cst = buf[pos-1] == buf[pos];

        if(pst && !cst)

        {

            pop(pst, buf, c, w);

            buf[0] = buf[1];

            c = pos = 1;

            pst = cst;

        }

        else if(!pst && cst || pos == BUF_N-1)

        {

            pop(pst, buf, c-1, w);

            buf[0] = buf[pos-1];

            c = 2;



            if(!cst)

            {

                buf[1] = buf[pos];

                pos = 2;

            }

            else

            {

                pos = 1;

                pst = ______________;  // 填空1

            }

        }

        else

        {

            c++;

            if(!pst) pos++;

        }

    } // while



    if(c>0) _____________________________;   // 填空2

}



void main()

{

    FILE* rfp;

    FILE* wfp;



    if((rfp=fopen(RFILE, "r")) == NULL)

    {

        printf("can not open %s!\n", RFILE);

        exit(1);

    }



    if((wfp=fopen(WFILE, "w")) == NULL)

    {

        printf("can not open %s!\n", WFILE);

        fclose(rfp);

        exit(2);

    }



    dopack(rfp, wfp);



    fclose(wfp);

    fclose(rfp);

}





【注意】

    只填写缺少的部分,不要抄写已有的代码。

    所填写代码不超过1条语句(句中不会含有分号)

    所填代码长度不超过256个字符。

    答案写在“解答.txt”中,不要写在这里!











      
View Code
#include <iostream>

#include <cstdio>

#include <windows.h>

using namespace std;



#define BUF_N  1000

#define RFILE "in.txt"

#define WFILE "out.txt"



void pop(int s, int* buf, int c, FILE* fp)

{

    int i;

    if(s)

    {

        fprintf(fp, "%d %d ", c, *buf);

    }

    else

    {

        fprintf(fp, "%d ", -c);

        for(i=0; i<c; i++)

        {

            fprintf(fp, "%d ", buf[i]);

        }

    }

}



void dopack(FILE* r, FILE* w)

{

    int buf[BUF_N];



    int pos = 0;  // 下一个数字在buf中将要存放的位置

    int c = 0;    // 当前段已读入的整数个数

    int pst; 

    int cst;



    while(fscanf(r, "%d", buf+pos)==1)

    {

        if(c==0)

        {

            c = pos = 1;

            continue;

        }



        if(c==1)

        {

            pst = buf[0] == buf[1];

            pos = pos + 1 - pst;

            c = 2;

            continue;

        }

        

        cst = buf[pos-1] == buf[pos];        //前后数字是否一致 

        if(pst && !cst)

        {

            pop(pst, buf, c, w);

            buf[0] = buf[1];

            c = pos = 1;

            pst = cst;

        }

        else if(!pst && cst || pos == BUF_N-1)

        {

            pop(pst, buf, c-1, w);

            buf[0] = buf[pos-1];

            c = 2;



            if(!cst)

            {

                buf[1] = buf[pos];

                pos = 2;

            }

            else    //前后一致 

            {

                pos = 1;

                pst = 1;     //老实说这个我是猜得...从上下文得知pst用于表示存储类型 

            }

        }

        else

        {

            c++;

            if(!pst) pos++;

        }

    } // while



    if(c>0) pop(pst, buf, c, w);;   // 填空2

}



int main()

{

    FILE* rfp;

    FILE* wfp;  



    if((rfp=fopen(RFILE, "r")) == NULL)

    {

        printf("can not open %s!\n", RFILE);

        exit(1);

    }



    if((wfp=fopen(WFILE, "w")) == NULL)

    {

        printf("can not open %s!\n", WFILE);

        fclose(rfp);

        exit(2);

    }



    dopack(rfp, wfp);



    fclose(wfp);

    fclose(rfp);

}
View Code

 

拼音字母

【编程题】(满分19分)



    在很多软件中,输入拼音的首写字母就可以快速定位到某个词条。比如,在铁路售票软件中,输入: “bj”就可以定位到“北京”。怎样在自己的软件中实现这个功能呢?问题的关键在于:对每个汉字必须能计算出它的拼音首字母。



    GB2312汉字编码方式中,一级汉字的3755个是按照拼音顺序排列的。我们可以利用这个特征,对常用汉字求拼音首字母。



    GB2312编码方案对每个汉字采用两个字节表示。第一个字节为区号,第二个字节为区中的偏移号。为了能与已有的ASCII编码兼容(中西文混排),区号和偏移编号都从0xA1开始。



    我们只要找到拼音a,b,c,...x,y,z 每个字母所对应的GB2312编码的第一个汉字,就可以定位所有一级汉字的拼音首字母了(不考虑多音字的情况)。下面这个表给出了前述信息。请你利用该表编写程序,求出常用汉字的拼音首字母。





a 啊 B0A1

b 芭 B0C5

c 擦 B2C1

d 搭 B4EE

e 蛾 B6EA

f 发 B7A2

g 噶 B8C1

h 哈 B9FE

j 击 BBF7

k 喀 BFA6

l 垃 C0AC

m 妈 C2E8

n 拿 C4C3

o 哦 C5B6

p 啪 C5BE

q 期 C6DA

r 然 C8BB

s 撒 C8F6

t 塌 CBFA

w 挖 CDDA

x 昔 CEF4

y 压 D1B9

z 匝 D4D1





【输入、输出格式要求】



    用户先输入一个整数n (n<100),表示接下来将有n行文本。接着输入n行中文串(每个串不超过50个汉字)。



    程序则输出n行,每行内容为用户输入的对应行的汉字的拼音首字母。



    字母间不留空格,全部使用大写字母。



    例如:

    用户输入:

3

大家爱科学

北京天安门广场

软件大赛



    则程序输出:

DJAKX

BJTAMGC

RJDS



【注意】



    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!

    

    在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。



    请把所有函数写在同一个文件中,调试好后,拷贝到【考生文件夹】下对应题号的“解答.txt”中即可。

    

    相关的工程文件不要拷入。

    

    源代码中不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。

    

    允许使用STL类库,但不能使用MFC或ATL等非ANSI c++标准的类库。



    例如,不能使用CString类型(属于MFC类库),不能使用randomize, random函数(不属于ANSI C++标准)
View Code
#include <iostream>

#include <map>

using namespace std;



map<char, int> a;

void init(void)

{

    a['A'] = 0xB0A1;

    a['B'] = 0xB0C5;

    a['C'] = 0xB2C1;

    a['D'] = 0xB4EE;

    a['E'] = 0xB6EA;

    a['F'] = 0xB7A2;

    a['G'] = 0xB8C1;

    a['H'] = 0xB9FE;

    a['J'] = 0xBBF7;

    a['K'] = 0xBFA6;

    a['L'] = 0xC0AC;

    a['M'] = 0xC2E8;

    a['N'] = 0xC4C3;

    a['O'] = 0xC5B6;

    a['P'] = 0xC5BE;

    a['Q'] = 0xC6DA;

    a['R'] = 0xC8BB;

    a['S'] = 0xC8F6;

    a['T'] = 0xCBFA;

    a['W'] = 0xCDDA;

    a['X'] = 0xCEF4;

    a['Y'] = 0xD1B9;

    a['Z'] = 0xD4D1;

}



char fun(char * str)

{

    int n = str[0];

    int m = str[1];

    int v = 0;

    for(int i = 7; i >= 0; i--)

    {

        if(n&(1<<i))

        {

            v |= (1<<(i+8));

        }

    }

    for(int i = 7; i >= 0; i--)

    {

        if(m&(1<<i))

        {

            v |= (1<<(i));

        }

    }

    map<char,int>::reverse_iterator rit;    //一定要声明为反向迭代器 

    for(rit = a.rbegin(); rit != a.rend(); rit++)

    {

        if(v >= rit->second)

        {

            return rit->first;

        }

    }

}



int main()

{

    init();

    int t;

    cin >> t;

    while(t--)

    {

        char s[100];

        cin >> s;

        for(int i = 0; s[i]; i += 2)

        {

            char ch[3] = {s[i], s[i + 1], '\0'};

            cout << fun(ch);

        }

        cout << endl;

    }

    

    return 0;

}
View Code

 

DNA比对

【编程题】(满分27分)



    脱氧核糖核酸即常说的DNA,是一类带有遗传信息的生物大分子。它由4种主要的脱氧核苷酸(dAMP、dGMP、dCMT和dTMP)通过磷酸二酯键连接而成。这4种核苷酸可以分别记为:A、G、C、T。



    DNA携带的遗传信息可以用形如:AGGTCGACTCCA.... 的串来表示。DNA在转录复制的过程中可能会发生随机的偏差,这才最终造就了生物的多样性。



    为了简化问题,我们假设,DNA在复制的时候可能出现的偏差是(理论上,对每个碱基被复制时,都可能出现偏差):



  1. 漏掉某个脱氧核苷酸。例如把 AGGT 复制成为:AGT



    2. 错码,例如把 AGGT 复制成了:AGCT



    3. 重码,例如把 AGGT 复制成了:AAGGT





    如果某DNA串a,最少要经过 n 次出错,才能变为DNA串b,则称这两个DNA串的距离为 n。



    例如:AGGTCATATTCC 与 CGGTCATATTC 的距离为 2



    你的任务是:编写程序,找到两个DNA串的距离。





【输入、输出格式要求】



    用户先输入整数n(n<100),表示接下来有2n行数据。



    接下来输入的2n行每2行表示一组要比对的DNA。(每行数据长度<10000)



    程序则输出n行,表示这n组DNA的距离。



    例如:用户输入:

3

AGCTAAGGCCTT

AGCTAAGGCCT

AGCTAAGGCCTT

AGGCTAAGGCCTT

AGCTAAGGCCTT

AGCTTAAGGCTT



    则程序应输出:

1

1

2





【注意】



    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!

    

    在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。



    请把所有函数写在同一个文件中,调试好后,拷贝到【考生文件夹】下对应题号的“解答.txt”中即可。

    

    相关的工程文件不要拷入。

    

    源代码中不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。

    

    允许使用STL类库,但不能使用MFC或ATL等非ANSI c++标准的类库。



    例如,不能使用CString类型(属于MFC类库),不能使用randomize, random函数(不属于ANSI C++标准)
View Code
#include <iostream>

#include <cstring>

#include <algorithm>

using namespace std;



const int N = 10000;

int main()

{

    int n;

    cin >> n;

    char a[N], b[N];

    while(n--)

    {

        cin >> a >> b;



        int d1[N + 1] = {0}, d2[N + 1] = {0};

        for(int i = 0; i <= N; i++)

        {

            d1[i] = i;

        }



        for(int i = 1; i <= strlen(a); i++)      //a(0, i)

        {

            d2[0] = i;

            for(int j = 1; j <= strlen(b); j++)  //b(0, j)

            {

                d2[j] = min(d2[j-1] + 1, d1[j] + 1);

                if(a[i - 1] == b[j - 1])

                {

                    d2[j] = min(d2[j], d1[j-1]);

                }

                else

                {

                    d2[j] = min(d2[j], d1[j-1] + 1);

                }

            }

            for(int k = 0; k <= N; k++)

            {

                d1[k] = d2[k];

            }

        }

        cout << d2[strlen(b)] << endl;

    }

    return 0;

}
View Code

 

方块填数

【编程题】(满分33分)



    “数独”是当下炙手可热的智力游戏。一般认为它的起源是“拉丁方块”,是大数学家欧拉于1783年发明的。



    如图[1.jpg]所示:6x6的小格被分为6个部分(图中用不同的颜色区分),每个部分含有6个小格(以下也称为分组)。

    

    开始的时候,某些小格中已经填写了字母(ABCDEF之一)。需要在所有剩下的小格中补填字母。



    全部填好后,必须满足如下约束:



    1. 所填字母只允许是A,B,C,D,E,F 中的某一个。



    2. 每行的6个小格中,所填写的字母不能重复。



    3. 每列的6个小格中,所填写的字母不能重复。



    4. 每个分组(参见图中不同颜色表示)包含的6个小格中,所填写的字母不能重复。



    为了表示上的方便,我们用下面的6阶方阵来表示图[1.jpg]对应的分组情况(组号为0~5):

000011

022013

221113

243333

244455

445555

 

    用下面的数据表示其已有字母的填写情况:

02C

03B

05A

20D

35E

53F



    很明显,第一列表示行号,第二列表示列号,第三列表示填写的字母。行号、列号都从0开始计算。



    一种可行的填写方案(此题刚好答案唯一)为:



E F C B D A

A C E D F B

D A B E C F

F B D C A E

B D F A E C

C E A F B D



    你的任务是:编写程序,对一般的拉丁方块问题求解,如果多解,要求找到所有解。



【输入、输出格式要求】



    用户首先输入6行数据,表示拉丁方块的分组情况。



    接着用户输入一个整数n (n<36), 表示接下来的数据行数



    接着输入n行数据,每行表示一个预先填写的字母。



    程序则输出所有可能的解(各个解间的顺序不重要)。



    每个解占用7行。



    即,先输出一个整数,表示该解的序号(从1开始),接着输出一个6x6的字母方阵,表示该解。



    解的字母之间用空格分开。



    如果找不到任何满足条件的解,则输出“无解”



    例如:用户输入:

000011

022013

221113

243333

244455

445555

6

02C

03B

05A

20D

35E

53F





    则程序输出:

1

E F C B D A

A C E D F B

D A B E C F

F B D C A E

B D F A E C

C E A F B D



   再如,用户输入:

001111

002113

022243

022443

544433

555553

7

04B

05A

13D

14C

24E

50C

51A

    则程序输出:

1

D C E F B A

E F A D C B

A B F C E D

B E D A F C

F D C B A E

C A B E D F

2

D C E F B A

E F A D C B

A D F B E C

B E C A F D

F B D C A E

C A B E D F

3

D C F E B A

A E B D C F

F D A C E B

B F E A D C

E B C F A D

C A D B F E

4

D C F E B A

B E A D C F

A D C F E B

F B E A D C

E F B C A D

C A D B F E

5

D C F E B A

E F A D C B

A B C F E D

B E D A F C

F D B C A E

C A E B D F

6

D C F E B A

E F A D C B

A B D F E C

B E C A F D

F D B C A E

C A E B D F

7

D C F E B A

E F A D C B

A D B F E C

B E C A F D

F B D C A E

C A E B D F

8

D C F E B A

F E A D C B

A D B C E F

B F E A D C

E B C F A D

C A D B F E

9

D C F E B A

F E A D C B

A F C B E D

B D E A F C

E B D C A F

C A B F D E





【注意】



    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!

    

    在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。



    请把所有函数写在同一个文件中,调试好后,拷贝到【考生文件夹】下对应题号的“解答.txt”中即可。

    

    相关的工程文件不要拷入。

    

    源代码中不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。

    

    允许使用STL类库,但不能使用MFC或ATL等非ANSI c++标准的类库。



    例如,不能使用CString类型(属于MFC类库);例如,不能使用randomize, random函数(不属于ANSI C++标准)
View Code

2012蓝桥杯本科组C/C++决赛题

#include <iostream>

#include <cstring>

using namespace std;



const int N = 6;

const char mark[N + 1] = "ABCDEF";

int n = 1;

char map[N][N], s[N][N];



bool input(void)

{

    int n;

    char x, y, c;

    for(int i = 0; i < N; i++)

    {

        for(int j = 0; j < N; j++)

        {

            cin >> map[i][j];

        }

    }

    (cin >> n).get();

    while(n--)

    {

        cin.get(x).get(y).get(c).get();

        s[x-48][y-48] = c;

    }

    return !cin.eof();

}



void clean(void)

{

    n = 1;

    memset(s, 0, sizeof(int) * N * N);

    memset(map, 0, sizeof(int) * N * N);

}



void display(void)

{

    for(int i = 0; i < N; i++)

    {

        for(int j = 0; j < N; j++)

        {

            cout << s[i][j] << " ";

        }

        cout << endl;

    }

}



bool isOK(int x, int y, char ch)

{

    for(int i = 0; i < N; i++)

    {

        if(s[i][y] == ch || s[x][i] == ch)

        {

            return false;

        }

        for(int j = 0; j < N; j++)

        {

            if(map[i][j] == map[x][y])

            {

                if(s[i][j] == ch)

                {

                    return false;

                }

            }

        }

    }

    return true;

}



void DFS(int x, int y)

{

    if(x == N && y == 0)

    {

        cout << n++ << endl;

        display();

        return;

    }

    if(s[x][y] == 0)

    {

        for(int i = 0; i < N ; i++)

        {

            if(isOK(x, y, mark[i]))

            {

                s[x][y] = mark[i];

                if(y == N - 1)

                {

                    DFS(x + 1, 0);

                }

                else

                {

                    DFS(x, y + 1);

                }

                s[x][y] = 0;

            }

        }

    }

    else

    {

        if(y == N - 1)

        {

            DFS(x + 1, 0);

        }

        else

        {

            DFS(x, y + 1);

        }

    }

}



int main()

{

    while(input())

    {

        DFS(0, 0);

        clean();

    }

    return 0;

}
View Code

 

你可能感兴趣的:(c/c++)