記事のディレクトリ
概要
この道路は主に考えDFSの主題に関連し、溶液プロセスは、別の古典的なトラックDFS + -------剪定問題与えられた8つのクイーン問題解決のプロセスになります与えています。
トピック1:選挙の問題の数
オリジナルタイトル説明
与えられたnは正の数は、ZJMはS.今ZJMの和が、それを得るためにどのように多くの方法を疑問に思うことをそれらの正確Kを選択することができます!
入力
最初の行、整数T <= 100は、テストケースの数を示します。各場合について、二行があります。、最初の行三つの整数は、第二のラインN、KおよびSを示し、nは整数は正の数を示します。
出力
それぞれの場合のために、整数は、独立した行に回答を示します。
サンプル入力
1
10 3 10
1 2 3 4 5 6 7 8 9 10
サンプル出力
4
タイトルリピート
比較的単純な質問が意図される、各時刻nのデジタル入力、この入力デジタルサンプルTの内部、選択K番号(各桁は一度だけ選択することができる)、したがってそれらの合計が、解決の合計値Sに等しいことこのような組み合わせの多くの種類があります。
Tソリューション全体のプロセス、すなわち、上述した処理を解消Tを実行し、2回行いました。
問題解決のためのアイデア
概要アイデア
ボード質問DFSのアイデアを、訪問されたか否かを各ポイントを格納する配列を使用し、としてDFS処理で何らかの処理を行う:(注:chosen_numの選択された数、値を選択和chosen_valueは、Kの数を制限しますオブジェクト値S)
状況 | アクションが取ら |
---|---|
chosen_num == K && chosen_value == S | 1の組み合わせの数 |
chosen_num <K && chosen_value> = S | 廃棄された剪定 |
chosen_num <K && chosen_value <S | DFSはダウンしました |
この戦略は、すべての場合に適用することができる列挙
データストレージ
使用
INTストア[20]。
各アクセスポイントを格納する、全ての点の初期設定が0に設定され、プロセスDFSは、それが1に設定されている場合、アクセス
なお、:DFSは、番号が選択番号に追加された場合、ストア[A]が1に設定され、下方に再帰DFSが完了した後、店[A]が0にリセットされ、それは保証することができ、部分ダウン続けます同じ層はストアアレイ内の利用可能な値を選択したときに同一です。
コードは以下の通りであります:
for(int i=begin;i<positive_number;i++)
{
if(store[i]==0)
{
store[i]=1;
dfs(number+1,addtion+store_number[i],i+1);
}
store[i]=0;//保证同层选择新数时,访问数组store[]情况完全一致
}
トピックの概要
比較的単純な問題のDFSボード、しかし、あなたがダウンしてDFS後、アレイリセット動作へのアクセスを追加しない場合、それは大きな問題DFSプロセスにつながることに注意してエラーが手書きで、ここで発生した場合、発生何回か前に首尾よく受け入れるリードをデバッグします。
改善されたポイントのトピック
ノー
元のタイトル
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int store_number[20];
int store[20];//存放每个点是否被访问过
int positive_number=0;//可供选择的数字个数
int add_number=0;//累计的数字个数
int num_addition=0;//累计的数字和
int sum_kind=0;//组合种类的个数
void dfs(int number,int addtion,int begin)
{
if(number==add_number && addtion==num_addition)
{
sum_kind++;
}
else if(number<add_number)
{
if(addtion>=num_addition)
return;
else
{
for(int i=begin;i<positive_number;i++)
{
if(store[i]==0)
{
store[i]=1;
dfs(number+1,addtion+store_number[i],i+1);
}
store[i]=0;
}
}
}
}
int main()
{
int bfs_times=0;
cin>>bfs_times;
for(int i=0;i<bfs_times;i++)
{
for(int k=0;k<20;k++)
{
store[k]=0;
}
cin>>positive_number>>add_number>>num_addition;
for(int j=0;j<positive_number;j++)
cin>>store_number[j];
dfs(0,0,0);
cout<<sum_kind<<endl;
sum_kind=0;
}
}
トピック2:8つのクイーン問題
オリジナルタイトル説明
エイトクイーン問題は、DFSクラシックのタイトルで、おそらくとして記述されているタイトルは、以下:
チェスでは、攻撃の女王とこの列の銀行の範囲は対角線の中心点を変更します。チェスボード8×8既存、および複数のソリューションがある場合、彼らは、お互いを攻撃しないように、このボードにオープン8つのクイーンを置くしようとすると、出力はすべてのソリューションを試してみてください。
出力
すべての可能な結果の出力。
サンプル出力
サンプル出力の一つの可能な結果:
1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
タイトルリピート
エイトクイーン問題は、ボード上に配置された8つのクイーンズを満たすために、それぞれのケースを見つけ、地図上の探索問題であり、そしてなしクイーン、全症例の出力各行及び対角クイーンズ。
問題解決のためのアイデア
概要アイデア
ライン0からの合法的な説明がない場合、女王が配置されているかどうか、このコラムでは銀行の位置と対角線を参照してください、この上の配置をテストするために、新しい場所に置かれ、それぞれ、クイーンズを置く開始し、 DFSのダウン、サブ法則ポイントリセット用と8行、表示プログラムの出力で満たされるまで、銀行の次のポイントを試してみてください。
チェック機能、大型の使用については、以下のコードを、それをカプセル化:
bool check_right(int x, int y, int map[8][8])
{
int left_x, left_y, right_x, right_y = 0;
if (x == 0)
{
return true;
}
for (int i = 0; i < x; i++)
{
if (map[i][y] == 1)
{
return false;
}
}
left_x = x-1; left_y = y-1;
right_x = x-1; right_y = y+1;
while (left_x >= 0 && left_y >= 0)
{
if (map[left_x][left_y] == 1)
{
return false;
}
left_x = left_x - 1;
left_y = left_y - 1;
}
while (right_x >= 0 && right_y < 8)
{
if (map[right_x][right_y] == 1)
{
return false;
}
right_x = right_x - 1;
right_y = right_y + 1;
}
return true;
}
データストレージ
2次元配列マップを使用してください[] []女王を置くかどうかを一律にすべての位置を保持します。初期化は、この位置に配置されたクイーンが正当である場合、それは1に設定され、0に設定されている
上記被験体は同じ点1、点まで、アレイは1にセットされ、パイロットの合法性検証動作が完了したマップことが注目されますそれを確実にするために、リセットしたときボードが完全に一致しているDFS、同じ層。リセットセクションのキーコードを次のように:
for (int the_col = 0; the_col < 8; the_col++)
{
map[row][the_col] = 1;
if (check_right(row, the_col, map))
{
if (row == 7)
print(map);
else
dfs(row + 1, map);
}
map[row][the_col] = 0;
}
トピック2つの概要
2つの質問は、手書きであり、その特性を解析した後、一般的な特性は、DFSクラス質問と結論付けることができる
1は、点は、一次元アレイは、アレイまたは高い、特定の形態であってもよいことは、データ構造にアクセスされたレコードを保持します関連の質問の意味。
2は、下向きのDFSの過程で、それぞれの新しいポイントを見つける、あなたは法的なの正当性を判断して、アクセスレコードの配列でマーキングダウン続けたい、ポイントをスキップするサブ規則は、Aにありましたポイント。
図3に示すように、アクセスポイントと同じ層で、選択し、層が新しい点の前に、選択した次のDFSを見つけるために、正当なポイント、場合、あなたがリセットをするために、レコードへのアクセスのこの配列を変更したいです新しいレイヤーを選択するときに同じポイントを確保するために、レコードのアクセスは、配列の値はまったく同じです。
トピック改善の二点
最初の行以外の行がある場合に、より一般的である、最適化の8つのクイーン問題は、問題の長期的な問題であるため、既存の状況を確認するために、新しい作品を入れて、あなたはこの列のものを試してみる必要はありません。またはクイーンこの点について対角線、列挙の数を減らす最大化するために剪定の、すなわち実現可能性は、リアルタイムの位置更新の対応するソースコードの最適化と最適化に続くました。高見場合は、寛大なアドバイスしてください。
タイトル二つのソース
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
int number = 0;
bool check_right(int x, int y, int map[8][8])
{
int left_x, left_y, right_x, right_y = 0;
if (x == 0)
{
return true;
}
for (int i = 0; i < x; i++)
{
if (map[i][y] == 1)
{
return false;
}
}
left_x = x-1; left_y = y-1;
right_x = x-1; right_y = y+1;
while (left_x >= 0 && left_y >= 0)
{
if (map[left_x][left_y] == 1)
{
return false;
}
left_x = left_x - 1;
left_y = left_y - 1;
}
while (right_x >= 0 && right_y < 8)
{
if (map[right_x][right_y] == 1)
{
return false;
}
right_x = right_x - 1;
right_y = right_y + 1;
}
return true;
}
void print(int map[8][8])
{
number++;
cout<<number<<":" <<endl;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if(map[i][j]==0)
cout<<"0"<<" ";
else
cout<<"1"<<" ";
}
cout << endl;
}
}
void dfs(int row, int map[8][8])
{
for (int the_col = 0; the_col < 8; the_col++)
{
map[row][the_col] = 1;
if (check_right(row, the_col, map))
{
if (row == 7)
print(map);
else
dfs(row + 1, map);
}
map[row][the_col] = 0;
}
}
int main()
{
int map[8][8];
memset(map, 0, sizeof(map));
dfs(0, map);
cout <<"八皇后问题的解决方案数量有:"<< number<<"个";
return 0;
}