White School algorithms: DFS permutations and combinations problems

ready:

Illustrate some of the terms and issues, and to facilitate understanding.
1. One index from the array start with, do not index 0.
2.dfs recursive called zero depth 1, depth 2 recursively called once, and so on.
3. The depth of each dfs some operations to be performed, a calculation operation deep space collectively.
4. In the arrangement of FIG explain traverse combination Solving

arrangement

Problem: Given a number of tables containing n elements, the number k selected from, many permutations may constitute
the output and each permutation of the total number of permutations, three wide field of each operand.
On the code:

#include <iostream>
#include <cstdio>
using namespace std;
int number[100];  //存储数表 
int book[100];  //哨兵 ,初始为0,代表未使用过 
int num[100];  //存储找到的排列 
int n,k,count;  //n为数表的长度,k为每个排列数包含的元素个数,count为总的排列数

void dfs(int step){
 if( step == k+1){    //step从 1 开始计算,当step == k+1 时,表示找到了一种排列 
  for(int i = 1;i<=k;i++)
   printf("%3d",num[i]); //输出排列数 
  printf("\n");
  count++;  //排列数个数 +1 
  return ;
 }
 for(int i = 1;i<=n;i++){
  if(book[i]==0){
   book[i]=1;   //标记点A, 1 表示该元素已用 
   num[step]=number[i];//将当前元素放在存储排列数的数组中 
   dfs(step+1);        //进入下一个深度空间 
   book[i]=0;   //标记点B,回溯时,将当前点标记为未用 
  }
 }
 
 return;
}

int main()
{
 scanf("%d %d",&n,&k);
 
 for(int i=1;i<=n;i++)  //注意,数组从 1 号索引开始使用 
  scanf("%d",&number[i]);
 printf("\n");
 dfs(1);         //进入dfs,当前:深度为1,递归0次 
 printf("%3d",count);
 return 0;
}

combination

Compositional Problem:
Given a number of tables containing n elements, which selected number k, the number of combinations may constitute
the output of each combination and the total number of combinations, each of the wide field number three
on the code:

#include <iostream>
#include <cstdio>
using namespace std;
int number[100]; //存放数表 
int num[100];  //存放查找到的组合数 
int count,n,k;   //count记录总的组合数个数,n为数表长度,k为每个组合数包含元素的个数

void dfs(int step,int startx) //step为深度,startx表示当前深度循环开始的索引 
{
 if(step == k+1){  //step从 1 开始计算,当step == k+1 时,表示找到了一种组合
  for(int i=1;i<=k;i++){
   cout << "   " << num[i];//输出找到的组合数 
  }
  cout << endl;
  count++;  //组合数个数 +1 
  return ;
 }
 for(int i=startx;i<=n;i++){
  num[step]=number[i];//将当前元素放在存储组合数的数组中 
  dfs(step+1,i+1); // i+1 表示下一深度的循环只能遍历当前索引之后的数(此处记为标记点C) 
 }
}

int main()
{
 cin >> n >> k;
 for(int i=1;i<=n;i++) //注意,数组从 1 号索引开始使用 
  cin >> number[i];
 dfs(1,1);  //进入dfs,当前:深度为1,递归0次,循环从第一个元素开始遍历 
 cout << "   " << count;
}

analysis

Focus of the analysis is that these two codes of different reasons. By exploring the reasons, in-depth understanding of the role of circulation and Sentinel.
It is easy to see, where the difference between these two codes:
a different starting point 1. cycle.
2. The use of a sentry, a not used.
Let's explore them by drawing different reasons.
Question the introduction: We will arrange a combination of problems, in thinking on the map. As shown below;
Here Insert Picture Description

One problem, the analysis arrangement

Question: In the figure of three elements, select any two elements constitute an arrangement, a total of how many options program?
Solution:
The first step: from when we1 Start walking, we can get 12 with13Two arrangements.
Step Two: When I from2Began to take the time, in accordance with the principles of the arrangement, I can have21with3Scheme two arrangements.
So the question is (recorded as issues X):
When I began to go from the 2, how do I ensure the operational space at a depth of 2, I can traverse all elements other than the elements have been traversed (that is 2 here) of?

Cycling debut

I set the loop to iterate1~nElements, then IYou can traverse space at each depth in operation all the elements. Here are all the elements , including of course already traversed element (this is2). So how Excluding traversed elements?

Great debut Sentinel

When we traverse each element, put the element is marked as already used , then the next deep space, the report by the Sentinel, we can avoid re-iterate the elements have been traversed. This is the role marked point A. Thus, the X problem is not solved yet?
So, there is a problem: Mark point B is doing what? Why do you want to go back in time and marked as the current elementUnusedIt?
Continue to explore, we give an chestnut:
Here Insert Picture Description
If there is no marker B :
When we1As a starting point to find12with13After, back to a depth of 1 operational space, and then the big question is, Sentinel reported: "We have no available element of!."
This is obviously not ah, this time to mark the role of point B is manifested.
We have to look at markers B situation:
find12with13After, we went back to the depth1Calculation space, this time, since the marker point B exists,1 and 2 and the element is marked as unusedSentinel report you say: "2No elements available! "Then we will be able to2As a starting point, continue to find new arrangement scheme.

Sentinel, under cyclic permutation problem in the next summary

Full cycle: Refers to traverse all the elements to ensure that can traverse all the elements in each operator's space spatial depth.
sentinel: Marker points A, arranged to ensure that when a single lookup, not aligned with the current element has been used;
marker point B, the guaranteed when looking for another permutation scheme can be used when using the arrangement of elements has been found.

Here that's a bit complicated, we give another chestnut explain:

Mark Point A: When I from1Start, recursive operation into the depth of space 2, I can no longer use1Number of elements.12(or13) Is the current arrangement ,1No element of the current arrangement is already used elements.
** marker B: ** when I find12with13Time (this time12with13Is the arrangement that has been found, 2 of arrangement is already looking for a used element), I still can2As a starting point to find a new arrangement program again.

Second problem: the combination of Analysis

Before we say. Combinations and permutations of code blocks in terms of using circulating and sentinel differences,
comparison arrangement, we have found that the combination does not use Sentry , and not the full cycle . Obviously, a combination of loop code used, his starting point is the current dfs depth (let us call this cycle to change the start-cycle ).

With our combination is not used to explore why the sentry, and using a variable-cycle starting point

Went to the time to move chestnuts (still above the figure in use):
Here Insert Picture Description
If we are using the Sentinel + full loop combination:
When we from2Start traversing ,, then we get21with23,(From1It was when traversing12) Then21with12Apparently repeated combinations.

How to avoid repeating that this combination of problems?

We first explore why there21This combination is repeated. Obviously, because we traverse the starting point2Before elements1, Element before the starting point if we do not traverse, not to repeat the combination does not appear yet? How to do it?

It becomes the starting point of circulation debut

By varying the starting point of the cycle, it is easy to ensure that the elements never before traversed starting point.

Let's explore why the combination under code does not use Sentinel

The remaining change after only a starting point-cycle traversing several tables starting point number, so the marker A and marker B issues addressed here do not appear, naturally you do not need a sentry. (No longer).

White produced, welcome Gangster wing

Here Insert Picture Description

Released two original articles · won praise 0 · Views 31

Guess you like

Origin blog.csdn.net/SX123q/article/details/104793373