【算法】矩阵填数,深度优先搜索(DFS),Pascal改C语言

qingsongzdq 2019-10-24

面向对象的上机实验

题目

以下列方式向 5*5 矩阵中填入数字。设数字i(1=<i<=25),则数字i+1 的坐标位置应为(E, W)。(E, W)可根据下列关系由(x,y)算出:

1)(E, W)=(x±3,y)

2)(E, W)=(x,y±3)

3)(E, W)=(x±2,y±2)

求解问题如下:

编写一个程序,当数字1被指定于某个起始位置时,列举出其它24个数字应在的位置;列举该条件下的所有可能方案。

参考答案

网上搜索到数学奥赛中本题的Pascal代码

来自http://blog.sina.com.cn/s/blog_1317189490102vp1k.html

Program lx9_1_3;
uses crt;
const n=5;
      d:array[1..8,1..2] of shortint=((3,0),(-3,0),(0,3),(0,-3),
                                      (2,2),(2,-2),(-2,2),(-2,-2));
var x0,y0:byte;
    a:array[1..n,1..n] of byte;
    total:longint;
 
procedure print;
  var i,j:integer;
  begin
    inc(total);
    gotoxy(1,3);
    writeln(‘[‘,total,‘]‘);
    for i:=1 to n do
      begin
        for j:=1 to n do
          write(a[i,j]:3);
        writeln;
      end;
  end;
 
procedure try(x,y,k:byte);
  var i,x1,y1:integer;
  begin
    for i:=1 to 8 do
      begin
        x1:=x+d[i,1];y1:=y+d[i,2];
        if (x1>0) and (y1>0) and (x1<=n)
           and (y1<=n) and (a[x1,y1]=0) then
             begin
               a[x1,y1]:=k;
               if k=n*n then print
                  else try(x1,y1,k+1);
               a[x1,y1]:=0;
             end;
      end;
  end;
 
begin
  clrscr;
  write(‘x0,y0=‘);readln(x0,y0);
  fillchar(a,sizeof(a),0);
  total:=0;a[x0,y0]:=1;
  try(x0,y0,2);
  writeln(‘Total=‘,total);
  writeln(‘Press any key to exit..。‘);
  repeat until keypressed;
end.

 自改C语言代码

运用了深度优先搜索算法。

可以输入一个起始位置的坐标后,列举出所有可能方案和方案个数。

也可以输出所有初始点方案的个数。

#include <stdio.h>
#define N 5//格子行列数 

int next[8][2]={{3,0},{-3,0},{0,3},{0,-3},{2,2},{2,-2},{-2,2},{-2,-2}};//下一步变换的位移 
int x0,y0;//输入的初始坐标 
int matrix[N][N];//存储nxn矩阵中的数字 
int total;//方案数量 

//打印一个矩阵的函数
void printMatrix(){
    int i,j;
    total+=1;//出来一次结果,就打印一次,方案数+1 
    printf("第%d种方案:\n",total);
    for(i=0;i<N;i++){
        for(j=0;j<N;j++){
            printf("%4d",matrix[i][j]);//%4d表示输出宽度为4,且右对齐
        }
        printf("\n");
    }
    printf("\n");
}
////每个初始点都输出方案的个数的话就不把每个方案打印出来了,太占地方 
//void printMatrix(){
//    int i,j;
//    total+=1;//出来一次结果,就打印一次,方案+1 
//}

//主要函数,(x,y)是矩阵内坐标,k是第几个数字
void try(x,y,k){
    int i,x1,y1;//x1,y1是本次要找的坐标
    //将8个位移都试一遍 
    for(i=0;i<8;i++){
        x1=x+next[i][0];
        y1=y+next[i][1];
        //如果该位置不超过边界且没有数字,则方案可行,把数字装进这个位置 
        if((x1>-1)&&(y1>-1)&&(x1<N)&&(y1<N)&&(matrix[x1][y1]==0)){
            matrix[x1][y1]=k;
            //如果k=25即已经搜索完,可以打印了
            if(k==N*N) 
                printMatrix();
            //如果还没到25,就继续搜索下一个位置 
            else 
                try(x1,y1,k+1);
            //本次打印完/本次搜索尝试到死路,回溯到上一节点去往另一分支前,将这一节点清零
            matrix[x1][y1]=0;
        }
    }
}


int main()
{
    //输入坐标
    printf("请输入第一个数的坐标(逗号间隔):"); 
    scanf("%d,%d",&x0,&y0); 

    //矩阵整体清0(第一条在dev-c++可以跑,vc++不行,还是用老办法)
    //memset(matrix, 0, sizeof(matrix));
    int i,j;
    for(i=0;i<N;i++){
        for(j=0;j<N;j++){
            matrix[i][j]=0;
        }
    }
    
    //数据初始化,运行 
    total=0;//方案数为零 
    x0-=1;y0-=1;//用户输入坐标从1开始,c语言数组从0开始
    matrix[x0][y0]=1;//第一个位置赋值1
    try(x0,y0,2); //从数字2开始放置
    
    printf("总共有%d种摆放方案\n\n",total);
    
    
//    //每个初始点都输出方案的个数 
//    int m,n;
//    for(m=0;m<5;m++){
//        for(n=0;n<5;n++){
//                x0=m;y0=n;
//                //矩阵整体清0 
//                int i,j; 
//                for(i=0;i<N;i++){
//                    for(j=0;j<N;j++){
//                        matrix[i][j]=0;
//                    }
//                }
//                total=0;//每次节点前方案数清零
//                matrix[x0][y0]=1;//第一个位置赋值1
//                try(x0,y0,2); //从数字2开始放置    
//                printf("数字1被指定于(%d,%d)有%d种方案\n",m+1,n+1,total);
//        }
//        printf("\n");//每5行之后打个空行好看点 
//    }
}

结果

  • 输入一个起始点坐标后输出的方案

【算法】矩阵填数,深度优先搜索(DFS),Pascal改C语言

【算法】矩阵填数,深度优先搜索(DFS),Pascal改C语言

  • 输出所有起始点的方案个数:

【算法】矩阵填数,深度优先搜索(DFS),Pascal改C语言

相关推荐