做了这道题加深了DFS回溯的理解,很有意义。
1.对于visit[]、vector结果集这种标记全局的变量,dfs后需要清除标记。回溯到i之前,visit[i]应该作为没访问过的点,所以需要还原。
2.对于history[i]这种对于后序dfs没有影响的变量,因为回溯到i之前的点,那么i点是什么数字对以后无影响,不需要还原标记。
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 10
int N;
int history[MAXN];
bool visit[MAXN];
vector<vector<int> >ans;
vector<int>line;
void dfs(int i)
{
int j, k;
if (i == N)
{
for (j = 0; j < N; j++)
{
printf("%d ", history[j]);
}
printf("\n");
return;
}
for (k = 1; k <= N; k++)
{
int ok = 1;
for (j = 0; j < i; j++)
{
if (history[j] == k)
ok = 0;
}
if (ok)
{
history[i] = k;//没必要回溯清除标记
dfs(i + 1);
}
}
}
void dfs_visit(int i)
{
int j, k;
if (i == N)
{
for (j = 0; j < N; j++)
{
printf("%d ", history[j]);
}
printf("\n");
return;
}
for (k = 1; k <= N; k++)
{
if(!visit[k])
{
visit[k]=true;
history[i] = k;//没必要回溯清除标记
dfs_visit(i + 1);
visit[k]=false;//有必要回溯清除标记
}
}
}
void dfs_vector(int i)
{
int j, k;
if (i == N)
{
ans.push_back(line);
}
for (k = 1; k <= N; k++)
{
if(!visit[k])
{
visit[k]=true;
line.push_back(k);
dfs_vector(i + 1);
visit[k]=false;//有必要回溯清除标记
line.pop_back();
}
}
}
int main()
{
N=3;
// dfs(0);
memset(visit, false, MAXN*sizeof(bool));
// dfs_visit(0);
dfs_vector(0);
for(int i=0; i<ans.size(); i++)
{
for(int j=0; j<ans[i].size(); j++)
cout<<ans[i][j];
cout<<endl;
}
return 0;
}