一,五种形式:
1.1排序树:孩子不与祖先重复
1.2组合树:孩子要大于父亲
1.3子集树:左孩子为0,右孩子为1
1.4拆分树:孩子要大于等于父亲
1.5搜索树:孩子不与祖前重复
二,判答案的两种方法
2.1判孩子(当根结点为虚空的时候适合,比如子集树,排列树,组合树,拆分树)
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
void dfs(int k);//第k层,第k代
int ans[N];//记录答案
int vis[N];//标记变量,去重
int main()
{
return 0;
}
void dfs(int k)
{
for(int i=1;i<=N;i++)//枚举第k代的所有孩子的线索
{
//生成孩子(用i表示出孩子)
if()//判孩子的合法性(符合约束条件并且不重复)
{
//保存孩子
//标记孩子
if()//如果孩子是答案就输出
{
}
else//如果孩子不是答案,继续从下一代找
{
dfs(k+1);
}
//取消标记
}
}
}
2.2判父亲(当根节点不是虚空的时候适合,比如搜索树)
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题的规模
void dfs(int u);//u为父亲结点
int ans[N];//记录答案
int vis[N];//标记变量,去重
int main()
{
return 0;
}
void dfs(int u)
{
//保存父亲
//标记父亲
if()//如果父亲是答案就输出(判父亲法)
{
//输出答案
}
else//如果父亲不是答案,继续从下一代找
{
for(int i=1;i<=N;i++)//枚举第u代的所有孩子的i
{
//生成孩子
if()//判断孩子的合法性
{
dfs(i);//递归搜索u的孩子
}
}
}
//取消标记
}
三,代码
3.1排序树
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
void dfs(int k);//第k层,第k代
int ans[N];//记录答案
int vis[N];//标记变量,去重
int main()
{
dfs(1);//从第一步开始
return 0;
}
void dfs(int k)
{
for(int i=1;i<=3;i++)//枚举第k代的所有孩子的线索
{
//生成孩子(用i表示出孩子)
if(vis[i]==0)//判孩子的合法性(符合约束条件并且不重复)
{
//保存孩子
ans[k]=i;
//标记孩子
vis[i]=1;
if(k>=3)//如果孩子是答案就输出
{
for(int j=1;j<=3;j++)
{
cout<<ans[j];
}
cout<<endl;
}
else//如果孩子不是答案,继续从下一代找
{
dfs(k+1);
}
//取消标记
vis[i]=0;
}
}
}
3.2组合树
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
void dfs(int k);//第k层,第k代
int ans[N];//记录答案
int n, r;//表示从n个树中选r个
int main()
{
cin>>n>>r;
dfs(1);
return 0;
}
void dfs(int k)
{
for(int i=1;i<=n;i++)//枚举第k代的所有孩子的线索
{
//生成孩子(用i表示出孩子)
if(i>ans[k-1])//判孩子的合法性(符合约束条件并且不重复),自动去重,不需要标记再去重
{
//保存孩子
ans[k]=i;
//标记孩子
if(k>=r)//如果孩子是答案就输出
{
for(int j=1;j<=k;j++)
{
cout<<ans[j]<<" ";
}
cout<<endl;
}
else//如果孩子不是答案,继续从下一代找
{
dfs(k+1);
}
//取消标记
}
}
}
3.3子集树
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
void dfs(int k);//第k层,第k代
int ans[N];//记录答案,ans[i]=0表示不选,ans[i]=1表示选
int n;//表示有n个物品
int main()
{
cin>>n;
dfs(1);
return 0;
}
void dfs(int k)
{
for(int i=0;i<=1;i++)//枚举第k代的所有孩子的线索
{
//生成孩子(用i表示出孩子)
if(1)//判孩子的合法性(符合约束条件并且不重复)
{
//保存孩子
ans[k]=i;
//标记孩子
if(k>=n)//如果孩子是答案就输出
{
for(int j=1;j<=k;j++)
{
cout<<ans[j]<<" ";
}
cout<<endl;
}
else//如果孩子不是答案,继续从下一代找
{
dfs(k+1);
}
//取消标记
}
}
}
3.4拆分树
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
void dfs(int s,int k);//第k层,第k代
int ans[N];//记录答案
int vis[N];//标记变量,去重
int n;
int main()
{
cin>>n;
ans[0]=1;//初始化一定要加
dfs(n,1);//将n进行拆分
return 0;
}
void dfs(int s,int k)
{
for(int i=1;i<=s;i++)//枚举第k代的所有孩子的线索
{
//生成孩子(用i表示出孩子)
if(i>=ans[k-1])//判孩子的合法性(符合约束条件并且不重复)
{
//保存孩子
ans[k]=i;
//标记孩子
s-=i;
if(s==0)//如果孩子是答案就输出
{
for(int j=1;j<=k;j++)
{
cout<<ans[j]<<" ";
}
cout<<endl;
}
else//如果孩子不是答案,继续从下一代找
{
dfs(s,k+1);
}
//取消标记
s+=i;
}
}
}
3.5搜索树(找出从起点到终点的所有路径)
#include<bits/stdc++.h>
using namespace std;
#define N 1000//问题规模的大小
//存储图
int n, m;//n个点,m条边
vector<int> a[N];
void dfs(int u,int k);//第k层,第k代
int ans[N];//记录答案
int vis[N];//标记变量,去重
//找从起点到终点的所有路径
int start=0;//起点
int target=2;//终点
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u, v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
dfs(start,1);
return 0;
}
void dfs(int u,int k)
{
//保存父亲
ans[k]=u;
//标记父亲
vis[u]=1;
if(u==target)//如果父亲是答案就输出(判父亲法)
{
//输出答案
for(int i=1;i<=k;i++)
{
cout<<ans[i]<<" ";
}
cout<<endl;
}
else//如果父亲不是答案,继续从下一代找
{
for(int i=0;i<a[u].size();i++)//枚举第u代的所有孩子的i
{
//生成孩子
int v=a[u][i];//u的第i个孩子
if(vis[v]==0)//判断孩子的合法性
{
dfs(v,k+1);//递归搜索u的孩子
}
}
}
//取消标记
vis[u]=0;
}
/*
5 7
0 1
0 3
0 4
1 2
1 4
2 3
3 4
*/