标题:骑士巡游问题
只看楼主
r2271135271
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2020-3-19
结帖率:66.67%
已结贴  问题点数:10 回复次数:6 
骑士巡游问题
1.想把定义棋盘大小放到主函数里,让用户在黑窗口定义
2.想显示出巡游次数
3.想用time()函数计算时间复杂度
#include<iostream>
#include<stdio.h>
using namespace std;

//定义棋盘的大小
#define N 12
#define LOSE 0
#define SUCCEED 1
void printknightgo(); //输出结果
int knightgo(int x,int y); //运算走法
int chessboard[N][N] = { 0 }; //建立棋盘
void main(){
    int x,y;
    printf("\n");
    printf("***************游戏开始!***************\n");
    cout<<"请输入坐标"<<endl;
    cin>>x>>y; //输入坐标
    if(knightgo(x,y)){ //开始运算走法,如果成功则返回成功,否则返回失败
        cout<<"成功完成"<<endl;
    }
    else{
        cout<<"失败"<<endl;
    }
    printknightgo(); //输出结果
}
//输出结果的算法
void printknightgo(){
    for(int i = 0;i < N; i++){
        for(int j = 0;j < N;j++){
            cout<<chessboard[i][j]<<"\t";
        }
        cout<<endl;
    }
}
int knightgo(int x,int y){
    chessboard[x][y] = 1;//将第一步标为1
    int step;//走的步数
    int nextx[8] = {-1,1,-2,2,-2,2,-1,1};//走的X的步法
    int nexty[8] = {2,2,1,1,-1,-1,-2,-2};//走的Y的步法
    int recordNextx[8]={0};//记住下步可走X的位置,并用count来记数
    int recordNexty[8]={0};//记住下步可走Y的位置,并用count来记数
    int tempx,tempy;//用于临时记住X和Y
    int i,j;//临时计数变量
    int count = 0;//记住可循环的个数
    int exist[8]={0};//第2次找8个方向每个可走的记录
    for(step=2;step <=N*N;step++){//把输进来或循环的位置,找下一个能走的位置,并记住这些位置和可走的个数
        for(i = 0;i < 8;i++){ //把上次记录重置0;
            recordNextx[i] = 0;
            recordNexty[i] = 0;
            exist[i] = 0;
        }
        count = 0;
        for(i = 0;i < 8;i++){//第一次循环,找可走的个位置,并记录可走方向的个数
            tempx = x + nextx[i];//tempx为临时记录X
            tempy = y + nexty[i];//tempy为临时记录Y
            if(chessboard[tempx][tempy] == 0 && tempx >= 0 && tempx < N && tempy >= 0 && tempy < N){//当这个位置没走过和不走出盘外时,才能记录
                recordNextx[count] = tempx;
                recordNexty[count] = tempy;//记录可走方向的x,y坐标
                count++; //记录可以走的方向的个数
            }
        }
        //把记住的位置,找他们的下个能走位置的个数,就是重复上面循环,只需记录可走方向的个数
        if(count == 0){//如果没有出路则返回失败
            return LOSE;
        }
        else {//如果只有一条路,则走这一条路
            if(count == 1){
                x = recordNextx[0];//因为可走方向只有一个,所记录中就有recordNext(x,y)[0];
                y = recordNexty[0];
                chessboard[x][y] = step; //把第几步写入这个棋盘的位置
            }
            else{//有多条路可以走的话
                for(j = 0;j < count;j++){//第一个点记录的可走的方向,并找出们下一个方向可以走的的方向的个数
                    for(i = 0;i < 8;i++){//找第2个点8个方向可走的方向
                        tempx = recordNextx[j] + nextx[i];
                        tempy = recordNexty[j] + nexty[i];
                        if(chessboard[tempx][tempy] == 0 && tempx >= 0 && tempx < N && tempy >= 0 && tempy < N){//当这个位置没走过和不走出盘外时,才能记录
                            exist[j]++;//记录第2个点可走方向的个数
                        }
                    }
                }
                //找最方向个数最小的一条路
                int min = exist[0];
                int last = 0;//用于记住,recordNext(x,y)中可走方向中,能走方向数目最小的一个方向
                for(i = 1;i < count;i++){//找出方向数目最小的数和方向
                    if(exist[i]<min){
                        min = exist[i];
                        last = i;
                    }
                }
                x = recordNextx[last];//将这个方向给x,y;
                y = recordNexty[last];
                chessboard[x][y] = step; //将这个步数写出这个棋盘
            }
        }
    }
    return SUCCEED;
}
运行结果:***************游戏开始!***************
请输入坐标
2 4
成功完成
97      20      69      24      95      2       59      26      53      4       49      28
70      23      96      21      68      25      54      3       58      27      52      5
19      98      71      102     1       94      67      60      55      50      29      48
72      101     22      93      108     103     86      57      46      61      6       51
99      18      135     112     105     92      107     66      85      56      47      30
136     73      100     109     134     113     104     87      82      45      62      7
17      132     123     138     111     106     91      114     65      84      31      44
74      137     110     133     122     125     116     83      88      81      8       63
131     16      143     124     139     90      119     80      115     64      43      32
144     75      140     121     128     117     126     89      42      35      38      9
15      130     77      142     13      120     79      118     11      40      33      36
76      141     14      129     78      127     12      41      34      37      10      39
Press any key to continue
搜索更多相关主题的帖子: int count 位置 记录 个数 
2020-07-14 13:36
r2271135271
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2020-3-19
得分:0 
有大佬帮忙嘛
2020-07-14 15:09
r2271135271
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2020-3-19
得分:0 
再追一下
(1)、游戏要有主菜单,如进入游戏、棋盘规模设置、迅游步数和路线展示、退出游戏等。
(2)、游戏初始时需要展示棋牌形态和骑士的初始位置,且界面清晰易读。
(3)、改变棋盘规模,如n=5,n=8,n=12,n=24等,记录每次实验所经历的运行时间。如采用time()函数,记录程序运行的起始终止时间,并求差值。分析算法的时间复杂度O(x),并尝试通过所采集的算法运行时间验证算法的时间复杂度分析O(x)。
有大佬指点嘛
2020-07-14 16:59
牧人马
Rank: 4
等 级:业余侠客
威 望:6
帖 子:49
专家分:229
注 册:2017-12-24
得分:5 
想把定义棋盘大小放到主函数里,让用户在黑窗口定义

用动态二维数组
程序代码:
    int n;
    cin >> n;
     int **p =  new int* [n];
     for(int i = 0; i < n; i++)
         p[i] = new int[n];

 
     for(int i = 0; i < n; i++)
         for(int j = 0; j < n; j++)
             p[i][j] =0;


 //释放空间:
for (int i = 0; i < n; i++) {
        delete[] p[i];
    }
    delete[] p;

想用time()函数计算时间复杂度

用clock()函数比较好,能精确到1/CLOCKS_PER_SEC秒,time函数只能精确到秒
头文件time.h
程序代码:
    clock_t s, e;
    s = clock();
//这里放代码段
    e = clock();
    cout << (double)(e - s)/CLOCKS_PER_SEC<<"s" << endl;


[此贴子已经被作者于2020-7-15 01:37编辑过]

2020-07-15 01:34
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:507
帖 子:8890
专家分:53117
注 册:2011-1-18
得分:5 
骑士巡游问题

“骑士巡游问题”是个啥问题?连题目都不想给?!

想显示出巡游次数

“巡游次数”又是个啥?难道不就是棋盘的大小嘛,也就是你代码中的 N*N。

想用time()函数计算时间复杂度

你这计算的是执行时间吧,而时间复杂度是描述算法随输入规模增涨的趋势。

我根据你的代码修改了一下,没改变你的算法(但我马虎,也许有bug没发现)。加入了 自定义棋盘大小 和 计时:
程序代码:
#include <algorithm>

bool knight( size_t row, size_t col, size_t rfirst, size_t cfirst, size_t* board )
{
    auto at = [&](size_t r, size_t c)->size_t& { return board[r*col+c]; };
    auto isempty = [&](size_t r, size_t c) { return r<row && c<col && at(r,c)==0; };

    if( rfirst>=row || cfirst>=col )
        return false;
    std::fill( board, board+row*col, 0 );
    at(rfirst,cfirst) = 1;

    const int nextr[8] = { -1, +1, -2, +2, -2, +2, -1, +1 };
    const int nextc[8] = { +2, +2, +1, +1, -1, -1, -2, -2 };
    for( size_t index=1; index!=row*col; ++index )
    {
        size_t mincount=0, nextstep_r=0, nextstep_c=0;
        for( size_t i=0; i!=8; ++i )
        {
            size_t n1r=rfirst+nextr[i], n1c=cfirst+nextc[i];
            if( isempty(n1r,n1c) )
            {
                size_t count = 1;
                for( size_t j=0; j!=8; ++j )
                {
                    size_t n2r=n1r+nextr[j], n2c=n1c+nextc[j];
                    count += isempty(n2r,n2c);
                }
                if( mincount==0 || count<mincount )
                {
                    mincount = count;
                    nextstep_r = n1r;
                    nextstep_c = n1c;
                }
            }
        }
        if( mincount == 0 )
            return false;

        rfirst = nextstep_r;
        cfirst = nextstep_c;
        at(rfirst,cfirst) = index+1;
    }
    return true;
}

#include <iostream>
#include <vector>
#include <chrono>
using namespace std;
using namespace std::chrono;

int main( void )
{
    size_t size, x, y;
    std::cout << "输入棋盘尺寸,及起始位置(例如“12 2 4”):";
    if( !(std::cin>>size>>x>>y) )
    {
        std::cerr << "输入错误.\n";
        return 1;
    }

    std::vector<size_t> board( size*size );
    auto t1 = steady_clock::now();
    bool b = knight(size,size,x,y,&board[0]);
    auto t2 = steady_clock::now();
    cout << "耗时 " << duration_cast<microseconds>(t2-t1).count() << "微秒.\n";
    if( !b )
        std::cout << "无解.\n";
    else
    {
        for( size_t i=0; i!=board.size(); ++i )
        std::cout << board[i] << "\t\n"[(i+1)%size==0];
    }
}
2020-07-15 10:42
r2271135271
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2020-3-19
得分:0 
回复 4楼 牧人马
大佬好 时间复杂度那个解决了 但是这个动态二维数组不是很明白
printf("***************游戏开始!***************\n");
    int N,i,j;
    int chessboard[N][N];
    cin >> N;
    int **p =  new int* [N];
    for(i = 0; i < N; i++)
        p[i] = new int[N];
    for(i = 0; i < N; i++)
        for(j = 0; j < N; j++)
            p[i][j] =0;
        //释放空间:
        for (i = 0; i < N; i++) {
            delete[] p[i];
        }
        delete[] p;
        cout<<"请输入坐标"<<endl;
这是我按照你写的放进我的代码,我之前是用define定义的N(大写),所以你的n改成了N,我在把#define N 14和int chessboard[N][N] = { 0 }; //建立棋盘删除后,出现了这些问题
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2057: expected constant expression
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2466: cannot allocate an array of constant size 0
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2057: expected constant expression
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2466: cannot allocate an array of constant size 0
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2087: '<Unknown>' : missing subscript
C:\Users\RQZ\Desktop\kt\c1.cpp(19) : error C2133: 'chessboard' : unknown size
C:\Users\RQZ\Desktop\kt\c1.cpp(48) : error C2065: 'N' : undeclared identifier
C:\Users\RQZ\Desktop\kt\c1.cpp(50) : error C2065: 'chessboard' : undeclared identifier
C:\Users\RQZ\Desktop\kt\c1.cpp(50) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(50) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(56) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(56) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(56) : error C2106: '=' : left operand must be l-value
C:\Users\RQZ\Desktop\kt\c1.cpp(76) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(76) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(90) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(90) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(90) : error C2106: '=' : left operand must be l-value
C:\Users\RQZ\Desktop\kt\c1.cpp(97) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(97) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(113) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(113) : error C2109: subscript requires array or pointer type
C:\Users\RQZ\Desktop\kt\c1.cpp(113) : error C2106: '=' : left operand must be l-value
执行 cl.exe 时出错.
不知道这部分哪错了,其他的没改动
2020-07-15 15:03
牧人马
Rank: 4
等 级:业余侠客
威 望:6
帖 子:49
专家分:229
注 册:2017-12-24
得分:0 
回复 6楼 r2271135271
如果你在#define N 12后仍然要用cin>>N来改变N的值,这个做法是错误的,宏定义相当于对源代码中的文本进行替换,一旦定下除非你修改代码中N的数值,否则在程序运行是无法修改N的值
如果不用宏定义,第二行N还没有初始化自然报错
程序代码:
    int N, i, j;
    //int chessboard[N][N];
    cin >> N;
    int** chessboard = new int* [N];
    for (i = 0; i < N; i++)
        chessboard[i] = new int[N];
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            chessboard[i][j] = 0;
    //输出
    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
        {
            cout << chessboard[i][j];
        }
        cout << endl;
    }
    //释放空间:
    for (i = 0; i < N; i++) {
        delete[] chessboard[i];
    }
    delete[] chessboard;

觉得不理解的话,5楼rjsp大佬里用的vector也是很方便的,可以学习下STL里的vector,不仔细抠数据结构的话,可以把vector当做动态数组去用

[此贴子已经被作者于2020-7-16 00:18编辑过]

2020-07-16 00:11



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-502516-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.233942 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved