【问题标题】:Complexity of a Chess Knight game国际象棋骑士游戏的复杂性
【发布时间】:2016-05-15 09:08:56
【问题描述】:

我在理解渐近分析或复杂性方面遇到问题,我尝试了以下link 并阅读完整的文章,但这并没有给我问题的最终答案,即:

我是否应该为每一行代码编写复杂性并将它们总结或其他?我的老师没有完全解释如何做到这一点,但希望它完成。

条件:一个骑士(国际象棋)必须穿过一个冰湖(m x n矩阵)并得到他的伙伴 从有给定障碍的湖的另一边。每次他 跳跃,他跳跃的矩阵的单元格成为障碍 (冰瀑布)。在他得到他的伙伴之后,他必须回到起点 点遵循不同的路线。起点是左下角单元格,他的好友位于右上角单元格

我对这个算法使用了回溯,剩下的问题是计算时间渐近复杂度。 代码如下:

#include<stdio.h>
#include<conio.h>
#define N 50
typedef struct{
   int x;
   int y;
} coordonate;
int sol=0,m,n;
coordonate vectSol[N];
void jump(int xL,int yL,int xD,int yD,int obstacole[N][N],int steps,coordonate road[N]);
int main(){
    int i,j,x,y,obstacole[N][N],nrObs;
    int KnightMatrixRoad[N][N], KnightMatrixBack[N][N];
    coordonate pathKnight[N],pathBack[N];
    printf("m=");
    scanf("%d",&m);
    printf("n=");
    scanf("%d",&n);
    printf("Nr. of obstacles: ");
    scanf("%d",&nrObs);
    for(i=0;i<nrObs;i++){
        printf("Insert obstacle %d through space bar (x,y):",i+1);
        scanf("%d %d",&x,&y);
        obstacole[y-1][x-1]=1;
    }
    jump(0,0,m-1,n-1,obstacole,0,pathKnight);
    for(i=0;i<=sol;i++){
        obstacole[vectSol[i].y][vectSol[i].x]=1;
        pathKnight[i]=vectSol[i];
        vectSol[i].x=0;
        vectSol[i].y=0;
    }
    sol=obstacole[n-1][m-1]=obstacole[0][0]=0;
    jump(m-1,n-1,0,0,obstacole,0,pathBack);
    for(i=0;i<=sol;i++){
        pathBack[i]=vectSol[i];
        vectSol[i].x=0;
        vectSol[i].y=0;
    }
    for(i=0;(pathKnight[i-1].x!=m-1) || (pathKnight[i-1].y!=n-1);i++){
        KnightMatrixRoad[pathKnight[i].y][pathKnight[i].x]=i;
    }
    puts("\nPath to his buddy:\n");
    for(i=n-1,sol=0;i>=0;i--){
        for(j=0;j<m;j++)
            printf("%3d",KnightMatrixRoad[i][j]);
        printf("\n\n");
    }
    for(i=0;((pathBack[i-1].x!=0) || (pathBack[i-1].y!=0)) || i==0;i++){
        KnightMatrixBack[pathBack[i].y][pathBack[i].x]=i;
    }
    puts("\nPath back to starting point:\n");
    for(i=n-1,sol=0;i>=0;i--){
        for(j=0;j<m;j++)
            printf("%3d",KnightMatrixBack[i][j]);
        printf("\n\n");
    }
    getch();
}
void jump(int xLocal,int yLocal,int xDest,int yDest,int obstacole[N][N],int steps,coordonate road[N]){
    int i,j;
    int tempObstacole[N][N];
    for(i=0;i<n;i++)
        for(j=0;j<m;j++){
            tempObstacole[i][j]=obstacole[i][j];
        }
    road[steps].x=xLocal;
    road[steps].y=yLocal;
    if(xLocal==xDest && yLocal==yDest){
        if(sol==0 || steps<sol){
            for(i=0;i<=sol;i++){
                vectSol[i].x=0;
                vectSol[i].y=0;
            }
            sol=steps;
            for(i=0;i<=sol;i++)
                vectSol[i]=road[i];
        }
    }
    if(sol==0 || steps+1<sol){
        tempObstacole[yLocal][xLocal]=1;
        if(yLocal+2<n && xLocal+1<m && !(tempObstacole[yLocal+2][xLocal+1]))
            jump(xLocal+1,yLocal+2,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal+2<n && xLocal-1>=0 && !(tempObstacole[yLocal+2][xLocal-1]))
            jump(xLocal-1,yLocal+2,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal-2>=0 && xLocal+1<m && !(tempObstacole[yLocal-2][xLocal+1]))
            jump(xLocal+1,yLocal-2,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal-2>=0 && xLocal-1>=0 && !(tempObstacole[yLocal-2][xLocal-1]))
            jump(xLocal-1,yLocal-2,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal+1<n && xLocal+2<m && !(tempObstacole[yLocal+1][xLocal+2]))
            jump(xLocal+2,yLocal+1,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal+1<n && xLocal-2>=0 && !(tempObstacole[yLocal+1][xLocal-2]))
            jump(xLocal-2,yLocal+1,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal-1>=0 && xLocal+2<m && !(tempObstacole[yLocal-1][xLocal+2]))
            jump(xLocal+2,yLocal-1,xDest,yDest,tempObstacole,steps+1,road);
        if(yLocal-1>=0 && xLocal-2>=0 && !(tempObstacole[yLocal-1][xLocal-2]))
            jump(xLocal-2,yLocal-1,xDest,yDest,tempObstacole,steps+1,road);
    }
}

【问题讨论】:

    标签: c time-complexity backtracking


    【解决方案1】:

    当你在分析代码时,你必须逐行分析它,计算每一个操作/识别时间复杂度,最后,你必须把它加起来才能得到全貌。

    例如,你可以有一个 线性复杂度的简单循环,但稍后在同一个程序中你可以有一个 三次复杂度的三重循环,所以你的程序将具有三次复杂度。增长的功能顺序在这里发挥作用。

    让我们看看算法的时间复杂度有哪些可能性,你可以看到我上面提到的增长顺序:

    • 常数时间1的增长顺序,例如:a = b + c

    • 对数时间有一个增长顺序LogN,通常出现 当您将某物一分为二(二分搜索、树、甚至循环)或以相同方式相乘时。

    • 线性,增长顺序为N,例如

      int p = 0;
      for (int i = 1; i < N; i++)
        p = p + 2;
      
    • 线性,增长顺序为n*logN,通常出现在分治算法中。

    • 三次,增长顺序N^3,经典示例是一个三元循环,您可以在其中检查所有三元组:

      int x = 0;
      for (int i = 0; i < N; i++)
         for (int j = 0; j < N; j++)
            for (int k = 0; k < N; k++)
                x = x + 2
      
    • 指数,增长顺序2^N,通常发生在您进行详尽搜索时,例如检查某个集合的子集。

    我认为你的老师想要了解整个情况,你会发现回溯算法非常非常慢。

    【讨论】:

    • 如果我理解正确的话,程序中一个部分的复杂度将是:for(i=0;i
    猜你喜欢
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 2015-05-02
    • 2023-03-29
    相关资源
    最近更新 更多