C05 The_ten_queens
08 The ten queens
注意:https://chanhuiseok.github.io/posts/baek-1/
youtube : n-queens problem
条件...?
通常はN*Nチェス盤(4<=N<=15)
N個の皇后を一緒に置いて、お互いに攻撃できないのであれば、数量を求める問題です.
++42ソウル:
1.皇后の位置を文字列で表す、
2.すべてのメソッドの合計数を返す必要があります.
Queenは、同じ行、同じ列、対角線/、方向が離せないという特徴があります.
->行ごとにQueenを配置し、フィーチャーの1つである行を考慮しないようにします.
では、対角線はどう判断するのか…?
xとyが同時に増加または減少した場合、この対角線が見つかります!\
\
\
\
この対角線はxを小さくしy値を大きくすることができる.
xを増やしてy値を減らすと見つかります! /
/
/
/
この場合、2つの条件に共通点があります:)
4*4地図上では、(2,1)に皇后が...
では(3、2)、(1、0)、
(1、2)、(0、3)および(3、0)は対角線に対応する.
|3 - 2| = |2 - 1|
|1 - 2| = |1 - 0|
|1 - 2| = |2 - 1|
ちょっと待って.
これらの値の絶対値|行番号差異|=|列番号差異|は同じです。
行番号の違い==列番号の違い=>同じ対角線上に!
△小学校、中学校で学んだ直線方程式y=x,y=-xを考えてみましょう.
また、問題では1次元文字列で表示して出力する必要があります.
アレイを使用して説明します.
0列(索引)の後の位置(行).第1列(索引)Queenの位置(行)
一行皇后の位置、二行皇后の位置.このように使えるので、1次元アレイでも十分です.
(==配列のインデックスを情報として使用!!)
問題は列皇后の位置(行)が表示されていることです.
同じローは表示されません.インデックス-インデックス==ロー-ローインデックス値は表示されません.
1142 = X !!! (行は同じ場所に置いてありました!!)
1423 = X !!! (2番目と3番目のインデックス差=1、2番目と3番目のロー差=1!)
もしそうであれば、次の条件が適用されます.
if (queen[i] != queen[cnt], i - cnt != queen[i] - queen[cnt])
できるはずです.
じょうけんけってい
int judge(int x, char *board)
{
int i;
int tmp;
i = 0;
while (i < x)
{
tmp = board[x] - board[i];
if (tmp < 0)
tmp *= -1;
if (board[x] == board[i] || x - i == tmp)
return (0);
i++;
}
return (1);
}
int nqueen(int x)
{
int i;
int cnt;
cnt = 0;
i = 0;
if (x == 10)
{
cnt++;
print...
return (cnt);
}
while (i < 10)
{
board[x] = i;
if (judge(x, board))
nqueen(x + 1);
i++;
}
return (cnt);
}
1.バックグラウンド追跡...
backtrackingはDFSに対する改良アルゴリズムである.
DFS:深度優先ナビゲーション
これはすべての方法に完全にナビゲートする方法です.
検索しないと正解にならない遡及により、検索効率が向上します!
=>>通常は「トリム」と呼ばれます.
ではDFSとは何でしょうか…?
ツリーまたはグラフィックでルートディレクトリを検索します.できるだけ深く見て、ない場合は他のルートディレクトリに戻って参照します.
再帰関数またはスタックを使用して実装します.
前のC問題では、再帰関数を使用したことがあると思います.
再帰関数を呼び出し、下部にwrite、putchar文を置き、最寄りから出力!!
差が少なくていいと思います!!
しかし、ここでは再帰関数を実行する条件を示します!
通常はN*Nチェス盤(4<=N<=15)
N個の皇后を一緒に置いて、お互いに攻撃できないのであれば、数量を求める問題です.
++42ソウル:
1.皇后の位置を文字列で表す、
2.すべてのメソッドの合計数を返す必要があります.
Queenは、同じ行、同じ列、対角線/、方向が離せないという特徴があります.
->行ごとにQueenを配置し、フィーチャーの1つである行を考慮しないようにします.
では、対角線はどう判断するのか…?
xとyが同時に増加または減少した場合、この対角線が見つかります!
\
\
\
\
この対角線はxを小さくしy値を大きくすることができる.xを増やしてy値を減らすと見つかります!
/
/
/
/
この場合、2つの条件に共通点があります:)4*4地図上では、(2,1)に皇后が...
では(3、2)、(1、0)、
(1、2)、(0、3)および(3、0)は対角線に対応する.
|3 - 2| = |2 - 1|
|1 - 2| = |1 - 0|
|1 - 2| = |2 - 1|
ちょっと待って.
これらの値の絶対値|行番号差異|=|列番号差異|は同じです。
行番号の違い==列番号の違い=>同じ対角線上に!
△小学校、中学校で学んだ直線方程式y=x,y=-xを考えてみましょう.
また、問題では1次元文字列で表示して出力する必要があります.
アレイを使用して説明します.
0列(索引)の後の位置(行).第1列(索引)Queenの位置(行)
一行皇后の位置、二行皇后の位置.このように使えるので、1次元アレイでも十分です.
(==配列のインデックスを情報として使用!!)
問題は列皇后の位置(行)が表示されていることです.
同じローは表示されません.インデックス-インデックス==ロー-ローインデックス値は表示されません.
1142 = X !!! (行は同じ場所に置いてありました!!)
1423 = X !!! (2番目と3番目のインデックス差=1、2番目と3番目のロー差=1!)
もしそうであれば、次の条件が適用されます.
if (queen[i] != queen[cnt], i - cnt != queen[i] - queen[cnt])
できるはずです.
じょうけんけってい
int judge(int x, char *board)
{
int i;
int tmp;
i = 0;
while (i < x)
{
tmp = board[x] - board[i];
if (tmp < 0)
tmp *= -1;
if (board[x] == board[i] || x - i == tmp)
return (0);
i++;
}
return (1);
}
int nqueen(int x)
{
int i;
int cnt;
cnt = 0;
i = 0;
if (x == 10)
{
cnt++;
print...
return (cnt);
}
while (i < 10)
{
board[x] = i;
if (judge(x, board))
nqueen(x + 1);
i++;
}
return (cnt);
}
1.バックグラウンド追跡...
backtrackingはDFSに対する改良アルゴリズムである.
DFS:深度優先ナビゲーション
これはすべての方法に完全にナビゲートする方法です.
検索しないと正解にならない遡及により、検索効率が向上します!
=>>通常は「トリム」と呼ばれます.
ではDFSとは何でしょうか…?
ツリーまたはグラフィックでルートディレクトリを検索します.できるだけ深く見て、ない場合は他のルートディレクトリに戻って参照します.
再帰関数またはスタックを使用して実装します.
前のC問題では、再帰関数を使用したことがあると思います.
再帰関数を呼び出し、下部にwrite、putchar文を置き、最寄りから出力!!
差が少なくていいと思います!!
しかし、ここでは再帰関数を実行する条件を示します!
アクセスするグラフィック、ツリー、配列のデータ構造が作成されました.
まず、繰り返し文でインデックスを変更します.
インデックスにすでにアクセスしている場合は、アクセスしません.
(+dfs)
もう一つ条件を与えて、条件を満たさないと枝を切って入らない!
(+バックトレース)
単純なソースコードの例
出典:ウィキペディア(dfs)
注意:https://youtu.be/7C9RgOcvkvo
const int MAX = 100'001;
bool visited[MAX]; // 방문 배열. visited[node] = true이면 node는 방문이 끝난 상태이다.
void dfs(const vector<int> graph[], int current) { // graph는 인접 리스트, current는 현재 노드
visited[current] = true; // current 방문
for(int next: graph[current]) { // current의 인접 노드를 확인한다. 이 노드를 next라고 하자.
if(!visited[next]) { // 만일 next에 방문하지 않았다면
dfs(graph, next); // next 방문
}
}
}
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_ten_queens_puzzle.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: hyojeong <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/02/12 01:13:42 by hyojeong #+# #+# */
/* Updated: 2022/02/14 09:40:48 by hyojeong ### ########.fr */
/* */
/* ************************************************************************** */
#include <unistd.h>
# 먼저, 해당 위치에 퀸을 놓을 수 있을지 판단하는 judge 함수
# ==> 백트래킹에 해당하겠죠!!!
int judge(int x, int board[])
{
int i;
int tmp;
i = 0;
while (i < x)
{
tmp = board[x] - board[i];
if (tmp < 0)
tmp *= -1;
if (board[x] == board[i] || x - i == tmp)
return (0);
i++;
}
return (1);
}
# 단순히 보드를 프린트해주는, 프린트 보드 함수
void print_board(int board[])
{
int index;
char tmp;
index = 0;
while (index < 10)
{
tmp = board[index] + 48;
write(1, &tmp, 1);
index++;
}
write(1, "\n", 1);
}
# 핵심. cnt의 값을 기록해주고, 해당 위치에 퀸을 놓을 수 있다면, 다음 열로 넘어가는, 재귀를 이용한 퀸 함수!
void queen(int x, int *cnt, int board[])
{
int i;
i = 0;
if (x == 10)
{
*cnt = *cnt + 1;
print_board(board);
return ;
}
while (i < 10)
{
board[x] = i;
if (judge(x, board))
queen(x + 1, cnt, board);
i++;
}
}
# cnt를 반환시키는, 문제에서 구현하라는 프로토타입 함수
int ft_ten_queens_puzzle(void)
{
int cnt;
int index;
int board[10];
cnt = 0;
index = 0;
while (index < 10)
board[index++] = 0;
queen(0, &cnt, board);
return (cnt);
}
潮流
まず、Boardに億円を充てる.
Quinn再帰関数を実行します.
インデックスのクイーンに入ることにします!!
2-1. quinn再帰関数ではboard[0]=0を入れて判断する.他の場所は皇后を埋め尽くしていないので、もちろん通過しました.
2-2. 次に、Boardの最初のインデックスにおけるQueenの位置を決定します.
しかし、この再帰関数は繰り返し文で実行され、以下にi++があるのではないでしょうか.
条件がそうであれば、また入って、そうでなければ、繰り返し文が再実行されます...
条件を満たすすべての皇后が出力され、個数が返されます.
Reference
この問題について(C05 The_ten_queens), 我々は、より多くの情報をここで見つけました https://velog.io/@1984/C05-Thetenqueensテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol