DFS 模板
int check(参数)
{
if(满足条件)
return 1;
else
return 0;
}
void dfs(int step)
{
判断边界
{
作相应操作;
}
for(尝试每一种可能)
{
满足check()条件
标记
记录结果
继续下一步dfs(step+1)
恢复初始状态(回溯时用到)
}
}
例题1 全排列
排列与组合是常用的数学方法。
先给一个正整数 ( 1 < = n < = 10 )
例如n=3,所有组合,并且按字典序输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
import java.util.Scanner;
public class Main {
//全排列
static int []a;
static int []vis;
static int n;
static int count=0;
static void dfs(int x)
{
if(x==n)
{
for(int i=0;i<n-1;i++)
{
System.out.print(a[i]+" ");
}
System.out.print(a[n-1]);
System.out.println();
return ;
}
else
{
for(int i=1;i<=n;i++)
{
if(vis[i]==0)//剪枝
{
vis[i]=1;
a[x]=i;//当前节点的可选值
dfs(x+1);//从该节点递归遍历
vis[i]=0;
}
}
}
}
@SuppressWarnings("resource")
public static void main(String[] args) {
Scanner scanner =new Scanner(System.in);
n=scanner.nextInt();
a=new int[n+1];
vis=new int[n+1];
dfs(0);
}
}
例题2.组合数
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你不用递归的方法输出所有组合。
例如n = 5 ,r = 3 ,所有组合为:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
import java.util.Scanner;
public class Main {
// 组合数递增输出
public static int n,m,k;
public static int []a=new int [100];
public static int []res=new int [100];
public static int []vis=new int [100];
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
n=scanner.nextInt();
m=scanner.nextInt();
for(int i=1;i<=n;i++)
{
a[i]=scanner.nextInt();
}
k=1;
dfs(0, 1);
}
public static void dfs(int step,int l)
{
if (step==m)
{
for(int i=1;i<=m;i++)
{
System.out.print(res[i]+" ");
}
System.out.println();
return ;
}
else
{
for(int i=1;i<=n;i++)
{
if (res[k-1]<a[i])
{
res[k++]=a[i];
dfs(step+1, i+1);//i+1,保证每次的结果递增
k--;
}
}
}
}
}
例题 3.组合数+素数筛选
import java.util.Scanner;
public class Main1{
//组合数+素数筛选
static int n,m,k,ans=0,sum=0;
static int []a=new int [100];//数据数组
static int []vis=new int [100];//标记数组
static int []res=new int [100];//保存结果的数组
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
n=scanner.nextInt();
m=scanner.nextInt();
for(int i=1;i<=n;i++)
{
a[i]=scanner.nextInt();
}
dfs(0,0,1);
System.out.println(ans);
}
public static void dfs(int step,int sum,int l)
{
if (step==m)
{
if (isPrim(sum))
ans++;
return ;
}
else
{
for(int i=l;i<=n;i++)
{
dfs(step+1, sum+a[i], i+1);
//不明白为什么用dfs(step,l)每次的和用sum保存为什么会超时
}
}
}
public static boolean isPrim(int n)//判断素数
{
if (n<1)
return false;
for(int i=2;i*i<=n;i++)
{
if (n%i==0)
return false;
}
return true;
}
}