POJ “顶嵌杯” 题目 代码 [菜鸟级别]

Problem A: 位操作

Description

假设你工作在一个32位的机器上,你需要将某一个外设寄存器的第X位设置成0(最低位为第0位,最高位为第31位),将第Y位开始的连续三位设置成110(从高位到低位的顺序),而其他位保持不变。对给定的寄存器值R,及X,Y,编程计算更改后的寄存器值R。

Input

仅一行,包括R,X,Y,以逗号","分隔,R为16进制表示的32位整数,X,Y在0-31之间且Y>=3,(Y-X)的绝对值>=3,保证两次置位不会重合

Output

更改后的寄存器值R(16进制输出)

Sample Input

12345678,0,3

 

Sample Output

1234567c

 

解题思路:

很简单的位操作,但是需要注意的是Y那里是 110,不能直接或上110,而是先两次SET,在CLR。dave就在这里浪费了有1个小时,惭愧

code

 
#include <stdio.h>
#define CLR(r, x)   r &= ~(1UL << x)
#define SET(r, y)   r |=  (1UL << y)
int main()
{
    int r, x, y;
    scanf("%x,%d,%d", &r, &x, &y);
    CLR(r,x);
    SET(r,y);
    SET(r,y-1);
    CLR(r,y-2);
    printf("%x", r);
    return 0;
} 

———————————————————————————————————————————————————————————————————————————————————————————————————————————————————— Problem B: 破译密码

Description

据说最早的密码来自于罗马的凯撒大帝。消息加密的办法是:对消息原文中的每个字母,分别用该字母之后的第5个字母替换(例如:消息原文中的每个字母A都分别替换成字母F)。而你要获得消息原文,也就是要将这个过程反过来。

密码字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z M

原文字母:V W X Y Z A B C D E F G H I J K L M N O P Q R S T U

注意:只有字母会发生替换,其他非字母的字符不变,并且消息原文的所有字母都是大写的。

Input

最多不超过100个数据集组成,每个数据集之间不会有空行,每个数据集由3部分组成:

  1. 起始行:START
  2. 密码消息:由1到200个字符组成一行,表示凯撒发出的一条消息.
  3. 结束行:END

在最后一个数据集之后,是另一行:ENDOFINPUT

Output

每个数据集对应一行,是凯撒的原始消息。

Sample Input

 

START

NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX

END

START

N BTZQI WFYMJW GJ KNWXY NS F QNYYQJ NGJWNFS ANQQFLJ YMFS XJHTSI NS WTRJ

END

START

IFSLJW PSTBX KZQQ BJQQ YMFY HFJXFW NX RTWJ IFSLJWTZX YMFS MJ

END

ENDOFINPUT

 

Sample Output

 

IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES

I WOULD RATHER BE FIRST IN A LITTLE IBERIAN VILLAGE THAN SECOND IN ROME

DANGER KNOWS FULL WELL THAT CAESAR IS MORE DANGEROUS THAN HE

 

解题思路

凯撒编码,判断字符是否是字母,并循环-5即可,记得要循环哦,非常简单的题目哦

code

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define N 202
char str[N]={0};
int main()
{
    char *p;
    gets(str);
    while( strcmp(str, "ENDOFINPUT") != 0 )
    {
        if ( (strcmp(str, "START") !=0)
            &&(strcmp(str, "END") != 0) )
        {
            for(p=str; *p !='/0'; p++)
            {
                if( isupper(*p) )
                    *p += *p-5 <'A' ? 26-5: -5;
            }
            puts(str);
        }
        gets(str);
    }
    return 0;
}

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

Problem C: 小孩报数问题

Description

有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。

Input

第一行输入小孩的人数N(N<=64)

接下来每行输入一个小孩的名字(人名不超过15个字符)

最后一行输入W,S (W < N),用逗号","间隔

Output

按人名输出小孩按顺序出列的顺序,每行输出一个人名

Sample Input

 

5

Xiaoming

Xiaohua

Xiaowang

Zhangsan

Lisi

2,3

 

Sample Output

 

Zhangsan

Xiaohua

Xiaoming

Xiaowang

Lisi

 

解题思路

 

约瑟夫环的问题,简单题目,但是dave一开始把题目看的不细心,以为是倒序输出,就花了很长时间用链表解决,结果超时(就算不超时也肯定错误),后来一看原来是正序,又用数组重写。 需要注意的就是第一次数人从当前s点就算第一个,以后数人下个人才算第一个,用一点点小技巧把第一数人的起始点向前退1个就ok了。这里也浪费了1个小时

 

 code

#include &lt;stdio.h&gt;
#define PEOPLE_NUM  65
#define NAME_LEN    16
struct people
{
    char name[NAME_LEN];
    char flag;
};
void input();
void calc();
struct people children[PEOPLE_NUM];
int n,w,s;
int main()
{
    input();
    calc();
    return 0;
}
void input()
{
    int i;
    scanf(&quot;%d/n&quot;, &n);
    for(i=1; i&lt;=n ;i++)
    {
        gets(children[i].name);
        children[i].flag=0;
    }
    scanf(&quot;%d,%d&quot;, &w, &s);
}
void calc()
{
    //struct people *p;
    int i ,out ,pos ;
    for(out=0,pos=w-1; out&lt;n ; out++)
    {
            for(i=0; i&lt;s;)
            {
                pos= (pos == n ? 1:pos+1);
                if(children[pos].flag == 0)
                    i++;
            }
            puts(children[pos].name);
            children[pos].flag = 1;
    }
}

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

Problem D: 时间日期格式转换

Description

世 界各地有多种格式来表示日期和时间。对于日期的常用格式,在中国常采用格式的是“年年年年/月月/日日”或写为英语缩略表示的”yyyy/mm/dd”, 此次编程大赛的启动日期“2009/11/07”就是符合这种格式的一个日期,而北美所用的日期格式则为“月月/日日/年年年年”或”mm/dd /yyyy”,如将“2009/11/07”改成这种格式,对应的则是”11/07/2009”。对于时间的格式,则常有12小时制和24小时制的表示方 法,24小时制用0-24来表示一天中的24小时,而12小时制只采用1-12表示小时,再加上am/pm来表示上午或下午,比如”17:30:00”是 采用24小时制来表示时间,而对应的12小时制的表示方法是”05:30:00pm”。注意12:00:00pm表示中午12点,而12:00:00am 表示凌晨12点。

对于给定的采用”yyyy/mm/dd”加24小时制(用短横线”-”连接)来表示日期和时间的字符串,请编程实现将其转换成”mm/dd/yyyy”加12小时制格式的字符串。

Input

第一行为一个整数T(T<=10),代表总共需要转换的时间日期字符串的数目。

接下来的总共T行,每行都是一个需要转换的时间日期字符串。

Output

分行输出转换之后的结果

Sample Input

 

2 2009/11/07-12:12:12

1970/01/01-00:01:01

 

Sample Output

 

11/07/2009-12:12:12pm

01/01/1970-12:01:01am

 

Hint

注意中午和凌晨时间的特殊表示

解题思路

算法简单但是功能稍微复杂的题目。

日期的变更可以利用向量循环移位的思路来解决,但是稍稍不同,因为yyyy/mm/dd循 环移位只能变成mm/ddyyyy/,所以要变通下。先y1y2y3y4翻转变成y4y3y2y1,在m1m2/d1d2翻转变成d2d1/m2m1,然 后整体y4y3y2y1/d2d1/m2m1翻转变成m1/m2/d1/2/y1/y2/y3/y4 解决。

日期的变更就只能用if语句按照小时来判断了,注意12小时制没有0点,最少1点,最多12点。我就是这个没有理解WA了两次,后来用手机测试了下,理解了变换步骤,终于解决。注意24小时制中的0点xx和12点xx变换都为12点am/pm.

code

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#define T   10
#define DATE_LEN 10
#define TIME_LEN 10
#define SUM_LEN  22
static void reverse(char a[], int n);
void change_date(char date[]);
void change_time(char time[]);
int t;
char datetime[T][SUM_LEN];
int main()
{
    int i;
    scanf(&quot;%d/n&quot;, &t);
    //scanf
    for(i=0; i&lt;t; i++)
    {
        gets(datetime[i]);
    }
    //change date & time
    for(i=0; i&lt;t; i++)
    {
        //date
        change_date(datetime[i]);
        //time
        change_time(datetime[i]+DATE_LEN+1);
    }
    //output
    for(i=0; i&lt;t; i++)
    {
        puts(datetime[i]);
    }
    return 0;
}
static void reverse(char a[], int n)
{
	int i;
	char t;
	for(i=0,n--; i&lt;n-i; i++)
	{
		t = a[i];
		a[i] = a[n-i];
		a[n-i] = t;
	}
}
void change_date(char date[])
{
	reverse(date, 4);
	reverse(date+5, 5);
	reverse(date, DATE_LEN);
}
void change_time(char time[])
{
    if ( (time[0]&gt;='1') && (time[1]&gt;='2') )
    {
        if( (time[0]!='1') || (time[1]!='2')  )
        {
            time[0] -= 1;
            time[1] -= 2;
        }
        strcat(time, &quot;pm&quot;);
    }
    else
    {
        if( (time[0]=='0') && (time[1]=='0')  )
        {
            time[0] += 1;
            time[1] += 2;
        }
        strcat(time, &quot;am&quot;);
    }
}&nbsp;

 

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

Problem E: 字母旋转游戏

Description

给定两个整数M,N,生成一个M*N的矩阵,矩阵中元素取值为A至Z的26个字母中的一个,A在左上角,其余各数按顺时针方向旋转前进,依次递增放置,当超过26时又从A开始填充。例如,当M=5,N=8时,矩阵中的内容如下: A B C D E F G H V W X Y Z A B I U J K L M N C J T I H G F E D K S R Q P O N M L

Input

M为行数,N为列数,其中M,N都为大于0的整数。

Output

分行输出相应的结果

Sample Input

 

4 9

 

Sample Output

 

A B C D E F G H I

V W X Y Z A B C J

U J I H G F E D K

T S R Q P O N M L

 

解题思路

稍微有点难度的题目,最重要的是矩阵四个边的边界值以及填充完成条件。在我的代码里,设置了四个变量u,d,l,r,分别代表上下左右的边界[u,d),[l,r),如果有两个边界重合就说明已经填充完毕了。当然你也可以用填充计数器来判断,如果等于行*列数,也是填满了。建立正确而又简洁的模型很重要。

code

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
void calc(char *ma, int m, int n);
void output(char *ma, int m, int n);
int main()
{
    int m=4, n=9;
    char *matrix;
    scanf(&quot;%d %d&quot;, &m, &n);
    matrix = malloc(m*n*sizeof(char));
    if (matrix == NULL)
        return -1;
    calc(matrix, m, n);
    output(matrix, m, n);
    return 0;
}
void output(char *ma, int m, int n)
{
    int i,j;
    for(i=0; i&lt;m; i++)
    {
        for(j=0; j&lt;n; j++)
        {
            printf(&quot;%4c&quot;, ma[n*i+j]);
        }
        puts(&quot;&quot;);
    }
}
void calc(char *ma, int m, int n)
{
    int i=0, j=-1;
    int u,d,l,r,sum;
    sum=0;
    u=0;
    d=m;
    l=0;
    r=n;
    while(1)
    {
        if (l==r)
            break;
        for(j++; j&lt;r; j++)
        {
            ma[n*i+j] = (sum++)%26 +'A';
        }
        u++;
        j--;
        if (u==d)
            break;
        for(i++; i&lt;d; i++)
        {
            ma[n*i+j] = (sum++)%26 +'A';
        }
        r--;
        i--;
        if (l==r)
            break;
        for(j--; j&gt;=l; j--)
        {
            ma[n*i+j] = (sum++)%26 +'A';
        }
        d--;
        j++;
        if (u==d)
            break;
        for(i--; i&gt;=u; i--)
        {
            ma[n*i+j] = (sum++)%26 +'A';
        }
        l++;
        i++;
    }
}

 

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

总结:

这5个小题,一共花了dave,6个小时的时间,看来自从高中OI以后,能力退化了很多。按照OI的水平这些题目都是2个小时完成的。更不说ACM了。。。

1、建立好模型再编码,与其花很多精力调试,不如一开始就把问题考虑全,这个能力跟做题经验有关。

2、读懂读清题目,第一题就是这样子,dave都不好意说了,还犯这样的低级错误。

3、调试的时候根据故障快速定位,不要漫无目的的。思考,很重要。

This entry was posted in 程序设计 and tagged . Bookmark the permalink.

45 Responses to POJ “顶嵌杯” 题目 代码 [菜鸟级别]

  1. wxwlll says:

    学习一下

  2. zydj_2006 says:

    感谢分享,你的文章已经推荐到学生大本营首页。

  3. davelv says:

    <div class="quote"><span class="q"><b>CSDN学生大本营辅导员 张媛(职业指导爱好者)<img src=image/group/admin.gif border=0></b>: 感谢分享,你的文章已经推荐到学生大本营首页。</span></div>谢谢辅导员推荐  ^^

  4. 原来 你高中就OI了呀!!

  5. levery says:

    题目确实没有什么难度,但是还是体现了模型的重要,模型实际上就是存储,存储设计好了,程序也就差不多了

  6. davelv says:

    <div class="quote"><span class="q"><b>中国地质大学(武汉) 杨辉鱼(C/C++学生)</b>: 原来 你高中就OI了呀!!</span></div>NOIP~很初级的比赛,NOI都进不了。

  7. davelv says:

    <div class="quote"><span class="q"><b>徐名峰(数据库老师)<img src=/image/teacher.gif border=0></b>: 题目确实没有什么难度,但是还是体现了模型的重要,模型实际上就是存储,存储设计好了,程序也就差不多了</span></div>老师说的没错,建立模型很重要。

  8. 不是很了解 OI还分级啊。。。

  9. davelv says:

    <div class="quote"><span class="q"><b>中国地质大学(武汉) 杨辉鱼(C/C++学生)</b>: 不是很了解 OI还分级啊。。。</span></div>就是省内NOIP,国家级NOI,国际级IOI

  10. 匿名用户 says:

    呵呵,写的很好~

  11. yangjian8915 says:

    时间转换格式。。  我这个也Accepted了。。

    #include <stdio.h>   

    #define N 10

    int main()   

    {   

            int yy, mm, dd, h, m, s;

            char pam;

            int t;

            int i = 0;

            char out[10][25];

            scanf("%d", &t);

            for (; i != t; ++i)

            {

                    pam = 'a';

                    scanf("%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d", &yy, &mm, &dd, &h, &m, &s);

                    if (h > 12)

                    {

                            h -= 12;

                            pam = 'p';

                    }

                    else if (h == 0)

                    {

        &nbs

  12. davelv says:

    <div class="quote"><span class="q"><b>南京邮电大学 杨健(C/C++学生)<img src=image/group/infor.gif border=0></b>: 时间转换格式。。  我这个也Accepted了。。

    #include <stdio.h>   

    #define N 10

    int main()   

    {   

            int yy, mm, dd, h, m, s;

            char pam;

            int t;

            i</span></div>比我的简单多了。不过你的程序好像不能通过示例代码

    12点不能正确转换。

  13. aoxuewawa says:

    完全没有考虑健壮性啊!

  14. davelv says:

    <div class="quote"><span class="q"><b>兰州交通大学 王丽萍(嵌入式学生)</b>: 完全没有考虑健壮性啊!</span></div>恩,没有考虑

  15. wade_2003 says:

    我都花了N长时间撒,学习了!

  16. dingtao199 says:

    [晕]poj啊,真令人神往

  17. stainxu says:

    好厉害啊!令人神往!

  18. geogre_jsj says:

    稍显繁琐了!不过模块化还不错

  19. aoxuewawa says:

    通过的人员将代码贴出来,都参考下如何?互相交流交流:。

  20. davelv says:

    <div class="quote"><span class="q"><b>兰州交通大学 王丽萍(嵌入式学生)</b>: 通过的人员将代码贴出来,都参考下如何?互相交流交流:。</span></div>那你发个日志,我去参考下。

  21. yangjian8915 says:

    <div class="quote"><span class="q"><b>我家 davelv(C/C++学生)</b>: 那你发个日志,我去参考下。</span></div>呵呵,发给你的当时没成功,提交上去的ACCEPTED了。  就是 多加个if(h == 12) pam = 'p'; 呵呵,按位的你的那个写的不错~

  22. yangjian8915 says:

    请问:

    #include <stdio.h>

    #include <string.h>

    void  cleanspace(char *str)

    {

            int  i,j=0;

            char sp[1024] = {'/0'};

            for (i = 0; i < strlen(str); i++)

            {

            if ( str<i> == ' ')

                    continue;

            else

                    sp[j++]=str<i>;

            }

            sp[j] = '/0';

            strcpy(str, sp);

    }

    int SafeStrcpy2KeyWord(char* pDestBuffer, char* pSourceString, int nDestBufferSize, char* szKeyWord)

    {

            char* ptr = NULL;

            char* source = pSourceString;

            char* dest = pDestBuffer;

            int len;

            if (strlen(pDestBuffer) >= 16 || strlen(pSourceString) >= 256)

            {

                    strcpy(dest, "NULL");

                &n

  23. yangjian8915 says:

    最后一个是   printf("%s/n", out[ i ]);

  24. davelv says:

    <div class="quote"><span class="q"><b>南京邮电大学 杨健(C/C++学生)</b>: 最后一个是   printf("%s/n", out[ i ]);</span></div>题目要求了几组数据,以eof结尾。

    你这个只能处理一组数据

  25. yangjian8915 says:

    <div class="quote"><span class="q"><b>我家 davelv(C/C++学生)</b>: 题目要求了几组数据,以eof结尾。

    你这个只能处理一组数据</span></div>可是我也用那个实现了。。。它说 Output limit error…

  26. #include<stdio.h>

    #include<string.h>

    int main()

    {

            int n;

            int yyyy,mm,dd,hour,minute,second;

            char *apm[2]={"am","pm"};

            char str[5];

            scanf("%d",&n);

            while(n–)

            {

                    scanf("%4d/%2d/%2d-%2d:%2d:%2d",&yyyy,&mm,&dd,&hour,&minute,&second);

                    //处理小时

                    if(hour>12)

                    {

                            strcpy(str,apm[1]);

                            hour-=12;

                    }

                    else

                    {

                            strcpy(str,apm[0]);

         

  27. 我无耻的将你的代码在我的电脑上敲了一遍,我突然发现你的编程风格很好,该空格的地方

    都有空格。而且模块化的思想很明显。学习了~~~~

  28. davelv says:

    <div class="quote"><span class="q"><b>南京邮电大学 杨健(C/C++学生)</b>: 可是我也用那个实现了。。。它说 Output limit error…</span></div>话说这个题目我也没做出来。那天感冒了,做了2个小时第一题就过不了,不爽。

  29. davelv says:

    <div class="quote"><span class="q"><b>罗响(C/C++学生)</b>: #include<stdio.h>

    #include<string.h>

    int main()

    {

            int n;

            int yyyy,mm,dd,hour,minute,second;

            char *apm[2]={"am","pm"</span></div>恩,是简单,不过函数太大了,分开一点更好。

  30. 还有就是,你经常把函数命名为calc()是什么意思?calculate吗?还有就是

    你说我的函数太大是什么意思?我没有用自定义的函数呢?

  31. davelv says:

    <div class="quote"><span class="q"><b>罗响(C/C++学生)</b>: 还有就是,你经常把函数命名为calc()是什么意思?calculate吗?还有就是

    你说我的函数太大是什么意思?我没有用自定义的函数呢?</span></div>calc是calculate的缩写,也就是计算的意思。一般题目我都分成input calc output三部分,简单的程序input和output就写到别的函数里面,复杂的话calc函数就继续拆分。

    函数太大就是说,你的函数内容太多了,最好把不同功能的部分都提取出来作为独立的函数使用。

  32. 哦,了解,你是说我模块化做的不够是吧?我这方面确实很欠缺啊,哈哈!

  33. 最后一题照你说的用判断总和的方法,可以通过

    void calc(char *ma,int m,int n)

    {

            int i=0,j=-1;

            int up=0,down=m,left=0,right=n,sum=0;

            while(1)

            {

                    for(j++; j<right ;j++)

                            ma[n*i+j] = (sum++)%26 +'A';

                    up++;

                    j–;

                    if(sum == m*n)

                            break;

                    for(i++; i<down ;i++)

                            ma[n*i+j] = (sum++)%26 +'A';

                    right–;

                    i–;

                    if(sum == m*n)

                            break;

              &nb

  34. 顺便说一下,你这个一维数组当二维数组的方法很有个性,还有前面j=-1有点技巧,这个技巧

    你在那个约瑟夫问题里也用过 啊。

  35. davelv says:

    <div class="quote"><span class="q"><b>罗响(C/C++学生)</b>: 顺便说一下,你这个一维数组当二维数组的方法很有个性,还有前面j=-1有点技巧,这个技巧

    你在那个约瑟夫问题里也用过 啊。</span></div>因为没有办法传长度未知的二维数组啊~就折中了。

    技巧我不太喜欢用,我比较喜欢写简洁实用的代码,但是水平有限,有的地方写不出来。

  36. yangjian8915 says:

    <div class="quote"><span class="q"><b>我家 davelv(C/C++学生)</b>: 话说这个题目我也没做出来。那天感冒了,做了2个小时第一题就过不了,不爽。</span></div>呵呵~~  我也是。。。。  过去了,锻炼一下~

回复 davelv 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注