Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4729635
  • 博文数量: 930
  • 博客积分: 12070
  • 博客等级: 上将
  • 技术积分: 11448
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-15 16:57
文章分类

全部博文(930)

文章存档

2011年(60)

2010年(220)

2009年(371)

2008年(279)

分类: C/C++

2009-05-12 18:08:47

网易的笔试题一道:
 
如图:
 
 
 
设“1”的坐标为(0,0) “7”的坐标为(-1,-1) 编写一个小程序,使程序做到输入坐标(X,Y)之后显示出相应的数字。
 
这个图有点像螺旋,它是按顺时针方向(由1->2->3->4->5…),逐渐向外膨胀。显然,如果以1为原点(0,0),以向右为x轴的正方向,以向下为y轴的正方向:
那么用人眼很容易就看出7的坐标为(-1,-1),这正与题目的假设一致。其他,如5的坐标应为(-1,1)。
但是,怎么让计算机知道呢?我的大脑突然不知所措,我在想,如果真出了这道题我挂定了^_^。但是,既然现在我是安然的坐在自己的卧室里,我绝对不会向它投降。
于是,躺在床上,望着天花板,想象着从这个螺旋的原点1出发,一起来看看:
Step1:从1向左走1步到达2。坐标(0,0)->(1,0),即x加1。
Step2:从2向下走1步到达3,坐标(0,1)->(1,1),即y加1。
Step3:从3向右走1步到达4,坐标(1,1)->(0,1),即x减1。
Step4:从4向右走1步到达5,坐标(0,1)->(-1,1),即x减1。
Step5:从5向上走1步到达6,坐标(-1,1)->(-1,0),即y减1。
Step6:从6向上走1步到达7,坐标(-1,0)->(-1,-1),即y减1。
……
当在大脑中想象着这一步一步的异同,一个灵感闪灵了。你是否发现了其中的规律?好吧,让我总结一下它的规律:
1、每向左(left)走一步,x就加1。每向右(right)走一步,x就减1。每向下(down)走一步,y就加1。每向上(up)走一步,y就减1。
这一条规律,只要有点直角坐标的知识,是显而易见的。当我们用程序去模拟这样一步一步地行走的时候,另外一个问题,就浮出水面了:怎样告诉计算 机,让它按照一个顺时针的螺旋方式,去遍历每一个结点?比如,当计算机来到结点2的时候,它怎么知道,下一步应该往下走呢?当计算机来到结点5的时候,它 怎么知道,下一点应该往上走呢?其实,这里还藏着另一条规律:
我把它叫做状态转换的规律。这个规律包含两个方面:
2.1、从结点1开始,
A、向右走
B、向下走
C、向左走
D、向上走
又回到A。形成一个循环,即:A->B->C->D->A->B……。
在每一个方向上,应该走多少步,才改变方向呢?现假设,现在开始改变方向,且已知上一次向右走了rNum步,向下走了dNum步,向左走了lNum步,向上走了uNum步。那么从现在开始,
2.2、沿新方向所走的步数,应该等于上一次相反方向所走的步数加1。例如,现在处于结点3,刚才从2->3的时候是往下走,现在要改变方向,向左走了。这个时候,由于上一次向右走了1步(即由1->2)。所以,这次应该向左走1+1=2步。
 
找到以上的两个规律,就可以写程序了。
我们可以用枚举类型,来标识四个方向(right,down,left,up)。
用四个整形变量,来记录上一次各个方向所走的步数(rNum,dNum,lNum,uNum)。
用四个整形变量,来记录在每一个方向累积所走的步数(rSum,dSum,lSum,uSum)。
这样,结点值就由这个公式确定:nodeVal = lSum+dSum+rSum+uSum+1。之所以加1,是因为原点的值为1,而不是0。
而坐标值可以这样确定:因为向右为x轴正方向,故x = rSum-lSum。因为向下为y轴的正方向,故y = dSum-uSum。


[root@mip-123456 163]# cat 163.c
#include<stdio.h>
#include<stdlib.h>

int find_res(int x,int y)
{
  int num = 1;

  if((x == 0)&&(y == 0))
    return 1;
  int flag = 1;
  int tmp_x = 0;
  int tmp_y = 0;
  int r_num = 0;
  int l_num = 0;
  int u_num = 0;
  int d_num = 0;
  int i;
  
  enum state{right,left,up,down};
  enum state state = right;

  while(flag)
  {
   switch(state)
    {
     case right:
         r_num = 0;
         for(i=0;i<l_num+1;i++)
           {
            r_num++;
            tmp_x++;
            num++;
           // printf("right num is %d\n",num);

            if((tmp_x == x)&&(tmp_y == y))
               {
                flag = 0;
                break;
               }
            }
            state = down;
           break;
     case down:
         d_num = 0;
         for(i=0;i<u_num+1;i++)
           {
            d_num++;
            tmp_y++;
            num++;
           // printf("down num is %d\n",num);

            if((tmp_x == x)&&(tmp_y == y))
               {
                flag = 0;
                break;
               }
            }
            state = left;
           break;
     case left:
         l_num = 0;
         for(i=0;i<r_num+1;i++)
           {
            l_num++;
            tmp_x--;
            num++;
           // printf("left num is %d\n",num);

            if((tmp_x == x)&&(tmp_y == y))
               {
                 flag = 0;
                 break;
                }
            }
            state = up;
           break;
     case up:
         u_num = 0;
         for(i=0;i<d_num+1;i++)
           {
            u_num++;
            tmp_y--;
            num++;
           // printf("up num is %d\n",num);

            if((tmp_x == x)&&(tmp_y == y))
               {
                flag = 0;
                break;
               }
            }
            state = right;
           break;
    default:
           break;
     }
  }
    return num;
}

int main(int argc,char* argv[])
{
 int i = 0;
 int j = 0;
 
  for(i=-1;i<=2;i++)
   {
    for(j = -1;j<=2;j++)
     {
        printf("(%d,%d) is %d\n",i,j,find_res(i,j));
      }
  }
 return 0;
}
[root@mip-123456 163]# ./163
(-1,-1) is 7
(-1,0) is 6
(-1,1) is 5
(-1,2) is 16
(0,-1) is 8
(0,0) is 1
(0,1) is 4
(0,2) is 15
(1,-1) is 9
(1,0) is 2
(1,1) is 3
(1,2) is 14
(2,-1) is 10
(2,0) is 11
(2,1) is 12
(2,2) is 13
[root@mip-123456 163]#

阅读(2371) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-02 13:29:18

楼主可能没有注意这个图中的简单数学性质,比如可以按照圈来算,第一圈4个数,第二圈8个,每往外扩展一圈便增加角上的四个数,按照这个性质,可以很容易知道,给出的坐标在第几圈上,从而算出点上的数字是多少

chinaunix网友2010-03-03 11:31:52

楼主的理论上坐标是无限大

chinaunix网友2009-08-27 16:05:48

a[][]={7,8,9,10..........} flagx=1,flagy=1 x=x+flagx,y=y+flagy; printf("%d",a[y][x]) 只需要这么一点逻辑就可以了,你可以试一试