9910请你编程

  大家好!《请你编程》又与你们见面了。《请你编程》得到了广大朋友的关心和支持,我们在这里表示衷心的感谢。《请你编程》是一个读者朋友直接参与的栏目,是一个体现自我的园地,希望有编程愿望的朋友,无论是编程高手,还是初学者都能参与进来,我们将会认真对待每一份作品。下面请看本期北京读者叶立超的程序。

9910请你编程解题思路

  1.建立如图1所示标系。对于给定的每一个点都有唯一的一组坐标,比如点1、2、3。

图1

  4、5、6、7的坐标分别是(1,1)、(1,2)、(2,1)、(1,3)、(2,2)、(3,1)、(1,4)。
  在该坐标系下每个点的x值等于其序号和其所在水平行前一行的最后一个点的序号之差,每一水平行线上的点的x值和y值之和等于所在行数加1。另外在每一组数中找出满足如下条件的六个顶点,其中第一个顶点peak[0]的y值最小并且x+y值最小,第二个顶点peak[1]的x值最小并且x+y值最小,第三个顶点peak[2]的x值最小并且y值最大,第四个顶点peak[3]的y大值最并且x+y值最大,第五个顶点peak[4]的x值最大并且x+y值最大,第六个顶点peak[5]的x值最大并且y值最小。当没有重合时,这六个点的相对位置如图2所示。
  2.判断这六个顶点构成的多边形是否为正多边形。当这六个点的相邻的点之间的连线均平行于x轴或y轴 或水平行线,并且这些连线中不为零的都相等时,如果这六个顶点不在一条直线上则其构成的多边形是满足要 求的正六边形或正四边形(其中两条边为零时)、或正三边形(其中三条边为零时)。
  3.最后判断这一组数中的每一个点是否都在这个正多边形的边上,满足这一条件的一组数就为正确结果。 源程序


  #include <math.h>
  #include <stdio.h>
  /*用于保存坐标的结构*/
  struct Coord
  {int x;
  int y;};
  /*将从文本中读取的点的号码dail转变为当前坐标系下的坐标并保存在point指向的坐标结构中*/
  void GetCoord(struct Coord *point,int dail);/*将满足顶点条件的点的坐标存入数组peak中*/
  void SetPeak(struct Coord peak[],struct Coord *point);
  /*判断数组peak中的点是否构成正多边形*/
  int Polygon(struct Coord peak[]);
  main()
  {int i,j; /*循环控制变量*/
  int linage;/*记录文本中待处理的数的行数*/
  int dail; /*接收从文本中读取的号码*/
  int sum; /*一行中点的总数*/
  int flag; /*标志变量*/
  struct Coord point[6];/*用于保存一行中每个点的坐标的数组*/
  struct Coord peak[6];/*用于保存六个顶点坐标的数组*/
  FILE *fp;
  if((fp=fopen(″pyramid.txt″,″r″))==NULL)/*打开文本*/
  {printf(″Can not open the ′pyramid.txt′ file!″);
  exit(0);}
  else
  printf(″The result is:\n″);
  fscanf(fp,″%d″,&linage); /*读取行数*/
<linage;i++) /*每次循环处理一行*/>   for(i=0;ibr>   {fscanf(fp,″%d″,&dail);/*读取行中的第一个数*/
  GetCoord(&point[0],dail); /*转换为坐标*/
  for(j=0;j<6;j++) /*初始化顶点坐标*/
  peak[j]=point[0]; /*都设置为第一个点的坐标*/
  for(j=1;fgetc(fp)!='\n'&&j<6;j++) /*处理一行数据*/
  {fscanf(fp,″%d″,&dail); /*读取一个号码*/
  GetCoord(&point[j],dail); /*转换为坐标*/
  SetPeak(peak,&point[j]); /*将满足顶点条件的点的坐标存入数组peak中*/}
  sum=j;/*记录该行的点的总数*/
  flag=Ploygon(peak); /*判断数组peak中的点是否构成正多边形*/
<sum&&flag;j++) /*进一步判断该行中每一个点是否都在这个正多边形的边上*/>   for(j=0;jbr>   {if(point[j].y!=peak[0].y&&
  point[j].y!=peak[2].y&&
  point[j].x!=peak[2].x&&
  point[j].x!=peak[4].x&&
  point[j].x+point[j].y!=peak[0].x+peak[0].y&&
  point[j].x+point[j].y!=peak[4].x+peak[4].y)
  flag=0;}
  if(flag) /*根据标志变量输出结果*/
  printf(″TRUE\n″);
  else
  printf(″FALSE\n″);}}
  /*将从文本中读得的序号dail转变为当前坐标系下的坐标并保存在point指向的坐标结构中*/
  void GetCoord(struct Coord *point,int dail)
  {int line; /*当前行的点的总数*/
  int span; /*所给点和上一行最后一个点的序号差*/
  line=1; /*从第一行开始*/
  span=dail;
  while(span>line) /*所给点和上行最后一个点的序号差大于当前行的点的总数*/
  {span-=line; /*序号差减去当前行的点的总数*/
  line++; /*当前行下移一行*/}
  point->x=span; /*所给点的x值等于其和前一行最后一个点的序号差*/
  point->y=(line+1)-span; /*x值和y值之和等于所在行数加1*/}
  /*将满足顶点条件的点的坐标存入数组peak中*/
  void SetPeak(struct Coord *peak,struct Coord *point)
  {if(point->y<=peak[0].y&&(point->x+point->y)<=(peak[0].x+peak[0].y))
  peak[0]=*point; /*第一个顶点的y值最小并且x+y值最小*/
  if(point->x<=peak[1].x&&(point->x+point->y)<=(peak[1].x+peak[1].y))
  peak[1]=*point; /*第二个顶点的x值最小并且x+y值最小*/
  if(point->x<=peak[2].x&&point->y>=peak[2].y)
  peak[2]=*point; /*第三个顶点的x值最小并且y值最大*/
  if(point->y>=peak[3].y&&(point->x+point->y)>=(peak[3].x+peak[3].y))
  peak[3]=*point; /*第四个顶点的y大值最并且x+y值最大*/
  if(point->x>=peak[4].x&&(point->x+point->y)>=(peak[3].x+peak[3].y))
  peak[4]=*point; /*第五个顶点的x值最大并且x+y值最大*/
  if(point->x>=peak[5].x&&point->y<=peak[5].y)
  peak[5]=*point; /*第六个顶点的x值最大并且y值最小*/}
  /*判断数组peak中的点是否构成正多边形*/
  int Ploygon(struct Coord *peak)
  {int i; /*循环控制变量*/
  int sidelen[6]; /*用于保存六条边长的数组sidelen*/
  /*各边必须平行于x轴或y轴或直线x+y=常数*/
  if(peak[0].x+peak[0].y!=peak[1].x+peak[1].y||
  peak[1].x!=peak[2].x||
  peak[2].y!=peak[3].y||
  peak[3].x+peak[3].y!=peak[4].x+peak[4].y||
  peak[4].x!=peak[5].x||
  peak[5].y!=peak[0].y)
  return 0;
   /*求各条边长并存入数组sidelen中*/
  for(i=0;i<6;i++)
  if(i==2)
  sidelen[i]=fabs(peak[i+1].x-peak[i].x);
  else if(i==5)
  sidelen[i]=fabs(peak[0].x-peak[i].x);
  else
  sidelen[i]=fabs(peak[i+1].y-peak[i].y);
  /*两条相邻的边同时为零时各顶点在一条直线上,不能构成多边形*/
   for(i=0;i<5;i++)
  if(sidelen[i]==0&&sidelen[i+1]==0)
  return 0;
  /*第一条边不为零时,若某边不为零并和第一条边长不相等,则不为正多边形*/
  if(sidelen[0])
  {for(i=1;i<6;i++)
  if(sidelen[i]&&sidelen[i]!=sidelen[0])
  return 0;}/*第一条边为零时,若某边不为零并和第二条边长不相等,则不为正多边形*/
  else
  for(i=2;i<6;i++)
  if(sidelen[i]&&sidelen[i]!=sidelen[1])
  return 0;
  return 1;}

9912请你编程题目

  在PopPush这个城市里,有一个非常著名的火车站。由于修建年代久远,这个车站只有一根轨道。而且,该车站又是终点站,所以火车进入和离开车站都依靠这个轨道,且只能从一端进出。该城市正是因此而得名。
  但这样一来,出现了一个很奇特的现象:如果有1、2、3这三列火车将先后进入车站,则火车出站的各种排列中不可能出现3、1、2。因为如果3是第一个进站的火车,说明1和2都已进站了。而2比1晚进车站,所以如果2还未出站的话,1不可能出站。但是,出站的各种排列中有可能出现1、2、3,即1进站后在2进站之前就已出站,2在3进站之前也出了站。
  程序要求如下:
  1.输入数据从文本文件rails.txt中读取。输入数据文件格式为:输入数据中又包含若干组;每一组的第一行为一个整数N,表示有N辆火车,N<=1000。以下每一行表示火车出站的排列顺序,用0来表示这组的结束;若N=0,则表示输入结束。
  2.若这种排列可能出现,则输出Yes,反之,输出No;每一组数据要空一行。
  注:排列序列中的1、2、3、4...表示在这些火车进站之前,它们的先后顺序。
  输入数据范例:
  5
  1 2 3 4 5
  5 4 1 2 3
  0
  6
  6 5 4 3 2 1
  0
  0
  输出数据范例:
  Yes
  No
  本期题目由上海的卜天明提供。
  来稿请寄磁盘稿或用E-mail(software@cpcw.com)投稿,请写明解题思路和源程序(包含详细的注解),寄到电脑报编辑部的收信地址或E-mail信箱。来稿截止日期:2000年1月15日。

本期获奖者名单

  (广西 陈行辉 ) (福建 蔡一鸣)
  (湖北 文峰) (天津 贾承欢)
  (山东 周文英) (重庆 王建)
  (北京 骆德全) (浙江 贺伟国)
  (上海 王卫国) (浙江 刘静)
  每位获奖者将获得苦丁香公司提供的光盘一张。