DFS(深度优先搜索)

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;
	     }
	}

推荐DFS入门

DF入门练习题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值