LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: chaiking

求算法

[复制链接]
发表于 2004-6-25 08:51:58 | 显示全部楼层
想象成一副2维的图(NxN), 我们要从(0,0)开始遍历这副图.
遍历的顺序是:
1) x=x+1, y=y     
2) x=x,   y=y+1,
3) x=x-1, y=y;
4) x=x    y=y-1;
然后回到 (1)

1-->2-->3-->4-->1....直到所有点都走过.
方向的改变条件是, 按当前方向走的话, 下一点出了图的范围或者已经访问过.
(撞到墙了)
按照这种思路写, 会比较清楚. 而且如果改变(1)-(4)的顺序,可以实现不同的效果.

[PHP]
#include "stdio.h"
int main()
{
  int n,i,j,n2,x,y,x1,y1,pos;
  int* array;
  int current_direction_index=0;
  const char search_directions[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
  printf("lease input a positive integer:");
  scanf("%d",&n);
  if(n<=0)
  {
     printf("go to somewhere else to play\n");
     return -1;
  }
  n2=n*n;
  array=(int*)malloc(sizeof(int)*n2);
  memset(array, 0, sizeof(int)*n2);
  x=0;y=0;
  for(i=1;i<=n2;++i)
  {
     pos=x+y*n;
     array[pos]=i;
     //find new x,y for the next number
         j=current_direction_index; //remember current dir
     while(1)
     {
             //first try current direction
             x1=x+search_directions[current_direction_index][0];
             y1=y+search_directions[current_direction_index][1];
             //if current direction OK.
             if(x1>=0 && x1<n && y1>=0 && y1<n && array[x1+y1*n]==0)
             {
                        x=x1;y=y1; break;
                 }
                current_direction_index=(current_direction_index+1)%4;
                if(j==current_direction_index)
                {
                        //something wrong, most likely the search directions are not properly set
                        //set i=n2, so that for loop will exit.
                        i=n2; break;
                }
         }
  }

  //print the array
  for(y=0;y<n;y++)
    for(x=0;x<n;x++)
  {
          pos=x+y*n;
          printf("%d", array[pos]);
          if(x==n-1) printf("\n");//last element in a row
          else printf("\t");
  }
  free(array);
}
[/PHP]
发表于 2004-6-26 16:24:00 | 显示全部楼层
最初由 landylau 发表
这个算法还是没看懂,等会再仔细看看,有点意思
虽然一看好像很简单,要我编一个还要想半天阿。等会试试



  1.    1    2    3    4    5    6    7    8
  2.    28   29   30   31   32   33   34    9
  3.    27   48   49   50   51   52   35   10
  4.    26   47   60   61   62   53   36   11
  5.    25   46   59   64   63   54   37   12
  6.    24   45   58   57   56   55   38   13
  7.    23   44   43   42   41   40   39   14
  8.    22   21   20   19   18   17   16   15
复制代码


看看这个阵形的规律就明白应该怎么做了:
1)n X n 的阵列;
2)要求往里旋转;
3)从9开始作为0圈算起,9到15有7个数,16到22有7个数;23到28有6个数,29到34有6个数;依此类推。。。故设置K变量进行计数,当走过下边或上边后,K++实现打印边长-1之目的;
4)打印的边界条件是最后一个数是为n&#178;,则停止;
5)让光标回到图形下面。
下面是源代码的详细注解:

  1. /*Redhat linux 9.0*/
  2. #include <stdio.h>
  3. main(void)
  4. {
  5.   int i, j, k, n;

  6.   printf("Please input number: ");
  7.   scanf("%d",&n);/*输入希望打印的边长*/

  8. /*用终端控制码清屏,并打印很多回车;以便下面用终端控制码实现光标向左向上移动*/
  9.   printf("\33[2J\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\33[20A");

  10.   for (i=1; i <= n; i++) printf("%5d",i);/*先打印出不参加循环的第一个边*/

  11. /*循环从第二个边开始,向内旋转*/
  12.   for (k=1, i=n+1;i <= n*n; i++)
  13.      {
  14.        for (j=1; j <= (n-k)&&i <= n*n; j++, i++)
  15.             printf("\33[1B\33[5D%5d",i);/*本循环打印右边*/
  16.        for (j=1; j <= (n-k)&&i <= n*n; j++, i++)
  17.             printf("\33[10D%5d",i);/*本循环打印下边*/
  18.        k++;/*过了下边后,边长应该-1*/
  19.        for (j=1; j <= (n-k)&&i <= n*n; j++, i++)
  20.             printf("\33[1A\33[5D%5d",i);/*本循环打印左边*/
  21.        for (j=1; j <= (n-k)&&i <= n*n; j++, i++)
  22.             printf("%5d",i);/*本循环打印上边*/
  23.        k++,i--;/*过了上边后,边长-1;i--修正了一下bug:避免有些值丢失*/
  24.       }

  25.   printf("\33[20B");/*打印终端控制码,让光标移动到图形的下面*/
  26. }
复制代码


注:有关终端控制码,参看shell版的精华部分。
发表于 2004-6-27 23:08:01 | 显示全部楼层
Only two nested for loops and one if-sentence can do the job: (without any 1- or 2-dimension arrays)

[PHP]#include <stdio.h>

int main() {
  int X, Y, x, y, round, result, n = 8;
  printf("lease input a number: ");
  scanf("%d",&n);
  for(y = 1; y <= n; y++) {
    for(x = 1; x <= n; x++) {
      X = (1 + n - abs(1 + n-2*x))/2;
      Y = (1 + n - abs(1 + n-2*y))/2;
      round = (X < Y ? X : Y) - 1;
      if (x >= y) {
        result = 4*round*(n-round) + x + y -1 - 2*round;
      } else {
        result = 4*(round+1)*(n-round-1) - x - y + 3 + 2*round;
      }
      printf("%5d", result);
    }
    printf("\n");
  }
  return 0;
}[/PHP]
发表于 2004-6-27 23:09:37 | 显示全部楼层
output when n = 10
  1. 1    2    3    4    5    6    7    8    9   10
  2. 36   37   38   39   40   41   42   43   44   11
  3. 35   64   65   66   67   68   69   70   45   12
  4. 34   63   84   85   86   87   88   71   46   13
  5. 33   62   83   96   97   98   89   72   47   14
  6. 32   61   82   95  100   99   90   73   48   15
  7. 31   60   81   94   93   92   91   74   49   16
  8. 30   59   80   79   78   77   76   75   50   17
  9. 29   58   57   56   55   54   53   52   51   18
  10. 28   27   26   25   24   23   22   21   20   19
复制代码
发表于 2004-7-2 02:14:34 | 显示全部楼层

受益匪浅!

值得学习
发表于 2006-9-10 01:01:18 | 显示全部楼层
如果不用终端控制码怎么做啊?我在面试时也见到过不过是在win32+c#或Java里面,要一次性打出来啊?
回复 支持 反对

使用道具 举报

发表于 2006-9-10 04:33:18 | 显示全部楼层
the solution I gave out does not require any console formating code
回复 支持 反对

使用道具 举报

发表于 2006-9-11 01:12:23 | 显示全部楼层
好久没有编程了,看到这个帖子后想练习一下编程,我的思路和dzho002兄相同,在这里复习一下链表和递归调用。
1-->2-->3-->4-->1....直到所有点都走过.
方向的改变条件是, 按当前方向走的话, 下一点出了图的范围或者已经访问过.
(撞到墙了)
按照这种思路写, 会比较清楚. 而且如果改变(1)-(4)的顺序,可以实现不同的效果.
  1. #include<stdio.h>
  2. #define MAX_ROW 16
  3. struct direction
  4. {
  5.         int dx;
  6.         int dy;
  7.         char name[5];
  8.         struct direction * next;
  9. };
  10. int main(void)
  11. {       
  12.         int data[MAX_ROW+2][MAX_ROW+2]={0};
  13.         int i=0,j=1,num=0;
  14.         struct direction d[4]={{0,1,"Right",},{1,0,"Down",},{0,-1,"Left",},{-1,0,"Up",}};
  15.         d[0].next=&d[1];
  16.         d[1].next=&d[2];
  17.         d[2].next=&d[3];
  18.         d[3].next=&d[0];
  19.         struct direction * direction=&d[0];
  20.         printf("Please enter a integer(not greater than %d)\n",MAX_ROW);
  21.         scanf("%d",&num);
  22.         if(num>MAX_ROW) exit(2);
  23.         data[num+1][num]=1;
  24.         data[num][0]=1;
  25.         data[1][num+1]=1;
  26.         findway(direction,1,0,data);
  27.         for(i=1;i<=num;i++){
  28.                 for(j=1;j<num;j++) printf("%4d",data[i][j]);
  29.                 printf("\n");
  30.         }
  31.         return 0;
  32. }
  33. void findway(struct direction * d,int x,int y,int data[MAX_ROW+2][MAX_ROW+2])
  34. {       
  35.         static int i=1;       
  36.         if (data[x+d->dx][y+d->dy]==0){
  37.         }
  38.         else{
  39.                 if (data[x+d->next->dx][y+d->next->dy]==0) d=d->next;
  40.                 else return;
  41.         }
  42.                 data[x+d->dx][y+d->dy]=i;
  43.                 i++;
  44.                 findway(d,x+d->dx,y+d->dy,data);
  45. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-9-11 09:11:35 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdlib.h>


  3. int main(int argc,char *argv[])
  4. {
  5.         int num;
  6.         int i = 0;
  7.         int j = 0;

  8.         if(argc < 2)
  9.         {
  10.                 printf("Usage: print_cycle_number number, where number is a positive int number\n");
  11.                 exit(1);
  12.         }

  13.         num = atoi(argv[1]);
  14.         if(num <= 0)
  15.         {
  16.                 printf("Usage: print_cycle_number number , where number is a positive int number\n");
  17.                 exit(1);
  18.         }


  19.         for(;j < num ;j++)
  20.         {
  21.                 for(i = 0;i < num ;i++)
  22.                 {
  23.                         if(i >= j && i + j <= num - 1)
  24.                                 // j cycle
  25.                                 printf("%5d",4 * (num - j) * j + i - j + 1);
  26.                         else if(i > j && i + j >= num - 1)
  27.                                 // num - 1 - i cycle
  28.                                 printf("%5d",(4 * (1 + i) * (num - 1 - i) + 1) + num - 2 * (num - 1 - i) - 1 + j - (num - 1 -i));
  29.                         else if(i <= j && i + j > num - 1)
  30.                                 // num - 1 - j cycle
  31.                                 printf("%5d",4 * (1 + j) * (num - 1 -j) + (num - 2 * (num - 1 - j) - 1) * 2 + num - i - (num - 1 - j));
  32.                         else if(i < j && i + j <= num - 1)
  33.                                 // i cycle
  34.                                 printf("%5d", 4 * (num - i) * i + (num - 2 * i - 1) * 3 + num  - i - j);
  35.                 }
  36.                 printf("\n");
  37.         }

  38.         return 0;
  39. }
复制代码

运行结果
  1. [root@arthur program]# ./print_cycle_number 20
  2.     1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20
  3.    76   77   78   79   80   81   82   83   84   85   86   87   88   89   90   91   92   93   94   21
  4.    75  144  145  146  147  148  149  150  151  152  153  154  155  156  157  158  159  160   95   22
  5.    74  143  204  205  206  207  208  209  210  211  212  213  214  215  216  217  218  161   96   23
  6.    73  142  203  256  257  258  259  260  261  262  263  264  265  266  267  268  219  162   97   24
  7.    72  141  202  255  300  301  302  303  304  305  306  307  308  309  310  269  220  163   98   25
  8.    71  140  201  254  299  336  337  338  339  340  341  342  343  344  311  270  221  164   99   26
  9.    70  139  200  253  298  335  364  365  366  367  368  369  370  345  312  271  222  165  100   27
  10.    69  138  199  252  297  334  363  384  385  386  387  388  371  346  313  272  223  166  101   28
  11.    68  137  198  251  296  333  362  383  396  397  398  389  372  347  314  273  224  167  102   29
  12.    67  136  197  250  295  332  361  382  395  400  399  390  373  348  315  274  225  168  103   30
  13.    66  135  196  249  294  331  360  381  394  393  392  391  374  349  316  275  226  169  104   31
  14.    65  134  195  248  293  330  359  380  379  378  377  376  375  350  317  276  227  170  105   32
  15.    64  133  194  247  292  329  358  357  356  355  354  353  352  351  318  277  228  171  106   33
  16.    63  132  193  246  291  328  327  326  325  324  323  322  321  320  319  278  229  172  107   34
  17.    62  131  192  245  290  289  288  287  286  285  284  283  282  281  280  279  230  173  108   35
  18.    61  130  191  244  243  242  241  240  239  238  237  236  235  234  233  232  231  174  109   36
  19.    60  129  190  189  188  187  186  185  184  183  182  181  180  179  178  177  176  175  110   37
  20.    59  128  127  126  125  124  123  122  121  120  119  118  117  116  115  114  113  112  111   38
  21.    58   57   56   55   54   53   52   51   50   49   48   47   46   45   44   43   42   41   40   39
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-9-11 15:12:04 | 显示全部楼层

  1. #include <stdio.h>
  2. #include <string.h>

  3. int direction = 1;        // 1右        2下        3左        4上

  4. int main(int argc, char **argv)
  5. {
  6.         int count, i, j, tmp;
  7.         int N = (argc == 2) ? atoi(argv[1]) : 10;
  8.        
  9.     tmp = 0;
  10.     i = j = 0;        
  11.     count = N * N;
  12.     int result[N][N];
  13.     memset(result, 0, count * sizeof(int));

  14.     while(tmp++ < count)
  15.     {
  16.         result[i][j] = tmp;
  17.         switch(direction)
  18.         {
  19.             case 1:
  20.                 if (j == N - 1 || result[i][j + 1] > 0)
  21.                 {
  22.                     i++;
  23.                     direction = 2;
  24.                 }   
  25.                 else
  26.                 {
  27.                     j++;
  28.                 }   
  29.                 break;
  30.             case 2:
  31.                 if (i == N - 1 || result[i + 1][j] > 0)
  32.                 {
  33.                     j--;
  34.                     direction = 3;
  35.                 }   
  36.                 else
  37.                 {
  38.                     i++;
  39.                 }   
  40.                 break;
  41.             case 3:
  42.                 if (j == 0 || result[i][j - 1] > 0)
  43.                 {
  44.                     i--;
  45.                     direction = 4;
  46.                 }   
  47.                 else
  48.                 {
  49.                     j--;
  50.                 }   
  51.                 break;
  52.             case 4:
  53.                 if (result[i - 1][j] > 0)
  54.                 {
  55.                     direction = 1;
  56.                     j++;
  57.                 }   
  58.                 else
  59.                 {
  60.                     i--;
  61.                 }   
  62.                 break;
  63.             default:
  64.                 break;
  65.         }   
  66.     }  
  67.     for (i = 0; i < N; i++)
  68.     {
  69.         for (j = 0; j < N; j++)
  70.         {
  71.             printf("%d\t", result[i][j]);
  72.         }   
  73.         printf("\n");
  74.     }   
  75.    
  76.     getchar();
  77.       
  78. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表