DFS其实是很灵活的,虽然我习惯按照
void dfs(int dep)
{
if(dep==n)
{}
else if(){
设置标记;
dfs(dep++);
清除标记;
}
}
这种形式。
但是有时候设置标记和清除标记拿到外面也是可以的,总之需要根据具体题目具体分析。
【还原标记】一般直接在数组(注意对以后的递归没有影响,可以覆盖)上修改的标记不用清除,
vector这种动态的,但是对dfs整体没有影响,只是辅助的,所以当vector是全局时需要pop还原;如果只是局部,那就不必还原。
visit这种对以后递归有影响的,回溯到i点之前,visit[i]应该视为没访问过,所以不管是全局还是局部,需要清除标记。
#include <iostream>
#include <vector>
using namespace std;
typedef struct point
{
int x, y;
} point;
const int MAXN = 20;
int g[MAXN][MAXN];
point vp[MAXN+MAXN];
vector<point> pvec;
void print_paths(int m, int n, int M, int N, int len)
{
if(g[m][n] == 0) return;
point p;
p.x=n;
p.y=m;
vp[len++] = p;
if(m == M && n == N)
{
for(int i=0; i<len; ++i)
cout<<"("<<vp[i].y<<", "<<vp[i].x<<")"<<" ";
cout<<endl;
}
else
{
print_paths(m, n+1, M, N, len);
print_paths(m+1, n, M, N, len);
}
}
void print_paths2(int m, int n, int M, int N, int len)
{
point p;
p.x=n;
p.y=m;
pvec.push_back(p);
if(m == M && n == N)
{
for(int i=0; i<pvec.size(); ++i)
cout<<"("<<pvec[i].y<<", "<<pvec[i].x<<")"<<" ";
cout<<endl;
}
else if(g[m][n] != 0)
{
print_paths2(m, n+1, M, N, len);
print_paths2(m+1, n, M, N, len);
}
pvec.pop_back();
}
int main()
{
freopen("8.2.in", "r", stdin);
int M, N;
cin>>M>>N;
for(int i=1; i<=M; ++i)
for(int j=1; j<=N; ++j)
cin>>g[i][j];
cout<<endl<<"all paths:"<<endl;
print_paths(1, 1, M, N, 0);
cout<<endl<<"all paths 2: "<<endl;
print_paths2(1, 1, M, N, 0);
fclose(stdin);
return 0;
}