论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

C趣味程序百例(17)

文章类别:C语言程序设计 | 发表日期:2008-9-24 14:44:47

55.哪个大夫哪天值班
56.区分旅客国籍
57.谁家孩子跑最慢





55.哪个大夫哪天值班
    医院有A、B、C、D、E、F、G七位大夫,在一星期内(星期一至星期天)每人要轮流值班一天。现在已知:
        A大夫比C大夫晚一天值班;
        D大夫比E大夫晚二天值班;
        B大夫比G大夫早三天值班;
        F大夫的值班日在B和C大夫的中间,且是星期四;
    请确定天天究竟是哪位大夫值班?
*问题分析与算法设计
    由题目可推出如下已知条件:
        *F是星期四值班;
        *B值班的日期在星期一至星期三,且三天后是G值班;
        *C值班的日期在星期五至星期六,且一天后是A值班;
        *E两天后是D值班;E值班的日期只能在星期一至星期三;
    在编程时用数组元素的下标1到7表示星期一到星期天,用数组元素的值分别表示A~F七位大夫。
*程序与程序注释
#include<stdio.h>
#include<stdlib.h>
int a[8];
    char *day[]={"","MONDAY","TUESDAY","WEDNESDAY","THURSDAYT",
                    "FRIDAY","SATUDAY","SUNDAY"};       /*建 立星期表*/
void main()
{
    int i,j,t;
    a[4]=6;               /*星期四是F值班*/    
    for(i=1;i<=3;i++)
    {
        a[i]=2;           /*假设B值班的日期*/
        if(!a[i+3]) a[i+3]=7;         /*若三天后无人值班则安排G值班*/
        else{  a[i]=0;continue;}      /*否则B值班的日期不断对*/
        for(t=1;t<=3;t++)             /*假设E值班的时间*/
        {
            if(!a[t]) a[t]=5;         /*若当天无人值班则安排E值班*/
            else continue;
            if(!a[t+2]) a[t+2]=4;     /*若E值班两天后无人值班则应为D*/
            else{  a[t]=0;continue;}   /*否则E值班的日期不对*/
            for(j=5;j<7;j++)
            {
                if(!a[j]) a[j]=3;      /*若当天无人值班,则安排C值班*/
                else continue;
                if(!a[j+1]) a[j+1]=1;  /*C之后一天无人值班则应当是A值班*/
                else{ a[j]=0;continue;}   /*否则A值班日期不对*/
                for(i=1;i<=7;i++)         /*安排完毕,输出结果*/
                    printf("Doctor %c is on duty %s.\n",'A'+a[i]-1,day[i]);
                exit(0);
            }
        }
    }
}
*运行结果
    Doctor E is on duty MONDAY.        (星期一:E)
    Doctor B is on duty TUESDAY.       (星期二:B)
    Doctor D is on duty WEDNESDAY.     (星期三:D)
    Doctor F is on duty THUESDAY.      (星期四:F)
    Doctor G is on duty FRIDAY.        (星期五:G)
    Doctor C is on duty SATURDAY.      (星期六:C)
    Doctor A is on duty SUNDAY.        (星期日:A)

*思考题
    在本题的求解过程中,我们只考虑了一星期之内的情况,没有考虑跨周的情况。对于“B大夫比G大夫早三天值班的”条件只是简单的认为是在同一周内早三天。若考虑跨周的情况就可能出现:B大夫星期一值班,而G大夫是上周的星期五。同样,对“F大夫的值班日在B和C大夫的中间”这个条件,也可以扩展为:“只要F大夫的值班日在B和C大夫的中间就可以”。
    请考虑答应跨周的情况下,可能的时间安排表。

-------------------------------------------------------

56.区分旅客国籍
    在一个旅馆中住着六个不同国籍的人,他们分别来自美国、德国、英国、法国、俄罗斯和意大利。他们的名字叫A、B、C、D、E和F。名字的顺序与上面的国籍不一定是相互对应的。现在已知:
    1)A美国人是医生。
    2)E和俄罗斯人是技师。
    3)C和德国人是技师。
    4)B和F曾经当过兵,而德国人从未参过军。
    5)法国人比A年龄大;意大利人比C年龄大。
    6)B同美国人下周要去西安旅行,而C同法国人下周要去杭州度假。
    试问由上述已知条件,A、B、C、D、E和F各是哪国人?
*问题分析与算法设计
    首先进行题目分析,尽可能利用已知条件,确定谁不是哪国人。
    由:1) 2) 3)可知:A不是美国人,E不是俄罗斯人,C不是德国人。另外因为A与德国人的职业不同,E与美、德人的职业不同,C与美、俄人的职业不同,故A不是俄罗斯人或德国人,E不是美国人或德国人,C不是美国人或俄罗斯人。
    由4)和5)可知B和F不是德国人,A不是法国人,C不是意大利人。
    由6)可知B不是美国人,也不是法国人(因B与法国人下周的旅行地点不同);C不是法国人。
        将以上结果汇总可以得到下列条件矩阵:
. 美(医生) 德(技师) 意大利 俄(教师)
A(医生) X . X X . X
B X . X X . .
C(技师) X . X X X X
D . . . . . .
E(教师) X . . X . X
F . . . X . .


根据此表使用消元法进行求解,可以方便地得到问题的答案。
    将条件矩阵输入计算机,用程序实现消去算法是很轻易的。
*程序与程序注释
#include<stdio.h>
char *m[7]={" ","U.S","U.K","FRANCE","GER","ITALI","EUSSIAN"};    /*国名*/
void main()
{
    int a[7][7],i,j,t,e,x,y;
    for(i=0;i<7;i++)           /*初始化条件矩阵*/
        for(j=0;j<7;j++)      /*行为人,列为国家,元素的值表示某人是该国人*/
            a[i][j]=j;
        for(i=1;i<7;i++)   /*条件矩阵每一列的第0号元素作为该列数据处理的标记*/
            a[0][i]=1;                 /*标记该列尚未处理*/
        a[1][1]=a[2][1]=a[3][1]=a[5][1]=0;         /*输入条件矩阵中的各种条件*/
        a[1][3]=a[2][3]=a[3][3]=0;             /*0表示不是该国的人*/
        a[1][4]=a[2][4]=a[3][4]=a[5][4]=a[6][4]=0;
        a[3][5]=0;
        a[1][6]=a[3][6]=a[5][6]=0;
        while(a[0][1]+a[0][2]+a[0][3]+a[0][4]+a[0][5]+a[0][6]>0)
        {                            /*当所有六列均处理完毕后退出循环*/
            for(i=1;i<7;i++)             /*i:列坐标*/
                if(a[0][i])              /*若该列尚未处理,则进行处理*/
                {
                    for(e=0,j=1;j<7;j++)     /*j:行坐标 e:该列中非0元素计数器*/
                        if(a[j][i]) {  x=j;y=i;e++;}
                    if(e==1)         /*若该列只有一个元素为非零,则进行消去操作*/
                    {
                        for(t=1;t<7;t++)
                            if(t!=i)a[x][t]=0;   /*将非零元素所在的行的其它元素置0*/
                        a[0][y]=0;                /*设置该列已处理完毕的标记*/
                    }
                }
        }
        for(i=1;i<7;i++)                          /*输出推理结果*/
        {
            printf("%c is coming from ",'A'-1+i);
            for(j=1;j<7;j++)
                if(a[i][j]!=0)
                {   printf("%s.\n",m[a[i][j>);  break;}
        }
}
*运行结果
    A is coming from ITALY.        (意大利人)
    B is coming from EUSSIAN.      (俄罗斯人)
    C is coming from U.K..         (英国人)
    D is coming from GER.          (德国人)
    E is coming from FRANCE.       (法国人)
    F is coming from U.S..         (美国人)
*问题的进一步讨论
    生成条件矩阵然后使用消去法进行推理判定是一种常用的方法。对于解决较为复杂的逻辑问题是十分有效的。

*思考题
    地理课上老师给出一张没有说明省份的中国地图,从中选出五个省从1到5编号,要大家写出省份的名称。交卷后五位同学每人只答了二个省份的名称如下,且每人只答对了一个省,问正确答案是什么?
        A 答:2号陕西,5号甘肃        B 答:2号湖北,4号山东
        C 答:1号山东,5号吉林        D 答:3号湖北,4号吉林
        E 答:2号甘肃,3号陕西       

--------------------------------------------------------------

57.谁家孩子跑最慢
    张王李三家各有三个小孩。一天,三家的九个孩子在一起比赛短跑,规定不分年龄大小,跑第一得9分,跑第2得8分,依此类推。比赛结果各家的总分相同,且这些孩子没有同时到达终点的,也没有一家的两个或三个孩子获得相连的名次。已知获第一名的是李家的孩子,获得第二的是王家的孩子。问获得最后一名的是谁家的孩子?
*问题分析与算法设计
    按题目的条件,共有1+2+3+...+9=45分,每家的孩子的得分应为15分。根据题意可知:获第一名的是李家的孩子,获第二名的是王家的孩子,则可推出:获第三名的一定是张家的孩子。由“这些孩子没有同时到达终点的”可知:名次不能并列,由“没有一家的两个或三个孩子获得相连的名次”可知:第四名不能是张家的孩子。
    程序中为了方便起见,直接用分数表示。
*程序与程序注释
#include<stdio.h>
int score[4][4];
void main()
{
    int i,j,k,who;
    score[1][1]=7;     /*按已知条件进行初始化:score[1]:张家三个孩子的得分*/ 
    score[2][1]=8;                 /*score[2]:王家三个孩子的得分*/
    score[3][1]=9;                 /*李家三个孩子的得分*/
    for(i=4;i<6;i++)               /*i:张家孩子在4到6分段可能的分数*/
        for(j=4;j<7;j++)           /*j:王家孩子在4到6分段可能的分数*/
            for(k=4;i!=j&&k<7;k++) /*k:李家孩子在4到6分段可能的分数*/
                if(k!=i&&k!=j&&15-i-score[1][1]!=15-j-score[2][1]    /*分数不能并列*/
                             &&15-i-score[1][1]!=15-k-score[3][1]
                             &&15-j-score[2][1]!=15-k-score[3][1])
                {
                    score[1][2]=i;score[1][3]=15-i-7;    /*将满足条件的结果记入数组*/
                    score[2][2]=j;score[2][3]=15-j-8;
                    score[3][2]=k;score[3][3]=15-k-9;
                }
        for(who=0,i=1;i<=3;i++,printf("\n"))
            for(j=1;j<=3;j++)
            {
                printf("%d",score[i][j]);     /*输出各家孩子的得分情况*/
                if(score[i][j]==1)who=i;      /*记录最后一名的家庭序号*/
            }
        if(who==1)                           /*输出最后判定的结果*/
            printf("The last one arrived to end is a child from family Zhang.\n");
        else if(who==2)
            printf("The last one arrived to end is a child from family Wang.\n");
        else printf("The last one arrived to end is a child from family Li.\n");
}
*运行结果
    7   5   3
    8   6   1
    9   4   2
    The last one arrived to end is a child from family Wang.
    (获得最后一名的是王家的孩子。

上一篇:{实例}C趣味程序百例(16) 人气:7025
下一篇:{实例}C趣味程序百例(18) 人气:6807
视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058