簡體   English   中英

C ++代碼示例:是什么使此循環如此多次?

[英]C++ code example: What makes this loop so many times?

我在這里找到一個代碼示例: N-QUEEN回溯問題已解決

它顯示以下代碼:

#include <iostream>
using namespace std;

/** this is the size of chess board */
#define N 8

/** Given a completed board, this prints it to the stdout */
void print_solution(int state[N][N])
{
    int i,j;
    for (i = 0; i < N; ++i)
    {
        for (j = 0; j < N; ++j)
            cout << state[i][j] << " ";
        cout << endl;
    }
    cout << endl;
}

/** return true if placing a queen on [row][col] is acceptable
else return false */
bool accept(int state[N][N], int row, int col)
{
    int i,j;

    /* check the column */
    for (i = 0; i < N; ++i)
    {
        if (state[row][i])
            return false;
    }

    /* check the row */
    for (i = 0; i < N; ++i)
    {
        if (state[i][col])
            return false;
    }

    /* check the upper left diagnol */
    for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
    {
        if (state[i][j])
            return false;
    }

    /* check the lower left diagnol */
    for (i = row, j = col; i < N && j >= 0; ++i, --j)
    {
        if (state[i][j])
            return false;
    }

    /* check the upper right diagnol */
    for (i = row, j = col; i >= 0 && j < N; i--, ++j)
    {
        if (state[i][j])
            return false;
    }

    /* check the lower right diagnol */
    for (i = row, j = col; i < N && j < N; ++i, ++j)
    {
        if (state[i][j])
            return false;
    }

    /* return true if all tests passed */
    return true;
}

void solve_state(int state[N][N], int row)
{

    int i;

    /* if all queens have been placed at non conflicting positions */
    if (row == N)
    {

        print_solution(state);
        return;
    }

    /* Place queens on all positions in a given row and
    check if the state is acceptable
    Continue the process till all possibilities found */
    for(i=0; i<N; ++i){

        if(accept(state, row, i)){
            state[row][i] = 1;
            solve_state(state, row+1);
        }
        state[row][i] = 0;
    }
}

int main()
{
    /* initialise the board */
    int state[N][N] = {0};

    solve_state (state, 0);

    return 0;
}

我在邏輯上相當失敗,嘗試學習遞歸等問題時遇到更大的麻煩。 真正令我煩惱的是,我只是無法理解為什么此代碼循環遍歷象棋問題中8個皇后區的所有92個解決方案。 起初我以為它只能找到一個解決方案,但是當我測試了代碼並運行了所有可能的解決方案時,我感到很驚訝。

我必須在這里遺漏一些非常基本的東西,因為我什至試圖在僅一種解決方案之后使其“停止”,但我只是失敗了。

所以我想我要問的是,為了理解這一點,給定這段代碼,如果我只想讓它循環一次並找到第一個解決方案,那么需要更改什么? 什么樣的魔術使這東西一直循環?

/* Place queens on all positions in a given row and
check if the state is acceptable
Continue the process till all possibilities found */
for(i=0; i<N; ++i){

    if(accept(state, row, i)){
        state[row][i] = 1;
        solve_state(state, row+1);
    }
    state[row][i] = 0;
}

此循環完全符合您的描述。 您在一行的八列上循環,從而提供了八種可能性。 如果要在第一個可接受的狀態上停止,則必須更新內部條件並刪除遞歸調用。 相反,您可以調用print_solution函數以打印結果。

這給您類似:

for(i=0; i<N; ++i){

    if(accept(state, row, i)){
        state[row][i] = 1;
        print_solution(state);
        return; // this prevents printing the solution multiple times
                // in case the queen may be placed on other colum on the same row
    }
    state[row][i] = 0;
}

旁注:對我來說,這段代碼是C代碼(在函數開始時聲明的變量,普通的舊C數組,在bool會起作用的地方使用int ),而唯一的C ++部分是對std::cout的使用。 std::coutstd::endlprint_solution函數中,可以很容易地用陳舊的printf替換。

理解遞歸方法的第一步是說出該方法的作用,如下所示:

/** solve_state(state, n) finds all possible solutions given a state where
 * the first n rows already have legally placed queens
 */

然后檢查該方法的主體並將其表達:

/**
 * if n == N we're done, there is a queen in every row.  print the solution.
 * otherwise for every legal spot in the current row, 
 * put a queen there, and then solve the remaining rows.
 */

在打印一種解決方案后退出程序的一種非常簡單的方法是在打印解決方案后引發異常。

或者,也許更優雅一些,您可以修改solve_state以在找到解決方案時返回1,並以此方式停止遞歸:

int solve_state(int state[N][N], int row)
{
    int i;

    /* if all queens have been placed at non conflicting positions */
    if (row == N)
    {
        print_solution(state);
        return 1; // done!
    }

    /* Place queens on all positions in a given row and
       check if the state is acceptable
       Continue the process till all possibilities found */
    for(i=0; i<N; ++i){
        if(accept(state, row, i)){
            state[row][i] = 1;
            if (solve_state(state, row+1)) return 1;
        }
        state[row][i] = 0;
    }

    return 0; // not yet
}

也許我的代碼會為您提供幫助,但我不是講英語的最佳人...

//coded by SwinGYOu

#include<iostream>
#pragma warning(disable:4996)
using namespace std;

/* this is the size of chess board */
const int boardSize=8;

/* Given a completed board, this prints it to the console */
void print_solution(int board[boardSize][boardSize], int i=0, int j=0){
    if(i==boardSize){ cout<<endl; return; }
    if(j==boardSize){ cout<<endl; print_solution(board, ++i, 0); return; }
    cout<<"[";
    if((i+j)%2)
        putwchar(board[i][j] ? '\u2655' : ' ');
    else
        putwchar(board[i][j] ? '\u265B' : ' ');
    cout<<"]";
    print_solution(board, i, ++j);
}
/* Check up, up left and up right to veritify that there are no other Queens, return true if right */
bool accept(int board[boardSize][boardSize], int row, int col, int rowD=0, int colD=0){
    if(!(rowD||colD)){
        return
            accept(board, row, col, -1, 0)&&
            accept(board, row, col, -1, -1)&&
            accept(board, row, col, -1, 1);
    }
    if(!(row>=0&&col>=0&&row<boardSize&&col<boardSize)){
        return true;
    }
    if(board[row][col]==1) return false;
    return accept(board, row+rowD, col+colD, rowD, colD);
}
/* check and return sultions for every sultion that possible*/
void solve_board(int board[boardSize][boardSize], int row=0, int col=0){
    //if the row befor was the last row of the table, its meants that is a sultion, print it.
    if(row==boardSize){
        print_solution(board);
        return;
    }
    //if col is out of the board, dont run check on it, its not a vaild path.
    if(col==boardSize) return;
    //run for this, if true, go to next row until end of row's or until a not vaild row is given than carry on with checking the next col.
    if(accept(board, row, col)){
        board[row][col]=1;
        solve_board(board, row+1);
    }
    board[row][col]=0;
    //carry on to next spot on the col in the given row.
    solve_board(board, row, col+1);
}

int main(){
    /* Make board */
    int board[boardSize][boardSize]={0};

    solve_board(board);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM