递归实现组合型枚举(java)

 

emm,前几天做的dfs的题,做完就忘记

今天突然一看那个笔记才发现原来自己真的不懂dfs 

dfs其实有点类似于动态规划
先定义状态 

起始状态 

终点状态

状态转移

定义状态 : 题目的要求是要求找出 n个数的排序情况,那么我们的每一个状态就可以看作是 i个数的排序状态

起始状态 :0 个数字的排序情况,也就是空数组 对吧

终点状况 : 如果找到了n个数的排序情况 ,我们就是输出长度为 n的数组的每一个元素,输出完成就回溯

状态转移:起点是如何一步一步的走到终点的呢?

我们逐层递归 然后如果某一个元素没有被访问过 我们就把他添加到数组中 

并把这个元素标记成已经访问过

然后进行递归

其实有的题目还需要剪枝 ,但这个题目不需要

这是主体思路

两个数组一个用来判断元素是否被访问过,一个用来存储元素,然后等到 终点情况 输出

dfs上下两部分是对称的



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;


public class Main{
	
//	定义一个数组用来标记是否被访问过
		static int flage[] =new int [100];
		static int Node[] = new int [100];
		static int n ;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 n =in.nextInt();
//		初始状态 一个数字 都没有选 
		dfs(0);
		out.close();
	}
//	表示已经添加的元素的数量
	static void dfs(int cnt) {
//		终止条件
		if(cnt==n) {
			for(int i=1;i<=n ; i++) {
				out.print(Node[i]+" ");
			}
//			输出完某种方案之后换行
			out.println();
//			回溯
			return;
		}
		for(int i=1; i<=n; i++) {
//			如果这个数字没有被访问过
			
			if(flage[i]==0) {
//				把这个元素放到下一个位置
				Node[cnt+1] = i ;
//				把这个元素标记成已经访问过了
				flage[i] = 1 ;
//				已经添加了 cnt+1 元素  向下递归
				dfs(cnt+1);
//				回复现场
				flage[i] =0; 
				Node[cnt+1] =0; 
				
				
			}
		}
		
		
	}
	


}

 这是完整代码,下面那部分是快读模板



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;


public class Main{
	
//	定义一个数组用来标记是否被访问过
		static int flage[] =new int [100];
		static int Node[] = new int [100];
		static int n ;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 n =in.nextInt();
//		初始状态 一个数字 都没有选 
		dfs(0);
		out.close();
	}
//	表示已经添加的元素的数量
	static void dfs(int cnt) {
//		终止条件
		if(cnt==n) {
			for(int i=1;i<=n ; i++) {
				out.print(Node[i]+" ");
			}
//			输出完某种方案之后换行
			out.println();
//			回溯
			return;
		}
		for(int i=1; i<=n; i++) {
//			如果这个数字没有被访问过
			
			if(flage[i]==0) {
//				把这个元素放到下一个位置
				Node[cnt+1] = i ;
//				把这个元素标记成已经访问过了
				flage[i] = 1 ;
//				已经添加了 cnt+1 元素  向下递归
				dfs(cnt+1);
//				回复现场
				flage[i] =0; 
				Node[cnt+1] =0; 
				
				
			}
		}
		
		
	}
	
// 快读模板
	static FastReader in =new FastReader();
	static PrintWriter out = new PrintWriter(System.out);
	static class FastReader{
		static BufferedReader br;
		static StringTokenizer st;
		
		public FastReader() {
			// TODO Auto-generated constructor stub
			br = new BufferedReader(new InputStreamReader(System.in));	
		}
		
	String next() {
		String str ="";
		
		while(st==null||!st.hasMoreElements()) {
			try {
				
					str  = br.readLine();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			st = new StringTokenizer(str);
			
		}
		return st.nextToken();
		}
	int nextInt() {
		return Integer.parseInt(next());
	}
	
		
		
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值