蓝桥杯 ADV-188 算法提高 排列数(java) 深度优先搜索 DFS

 算法提高 排列数  
时间限制:1.0s   内存限制:256.0MB
    
问题描述
  0、1、2三个数字的全排列有六种,按照字母序排列如下:
  012、021、102、120、201、210
  输入一个数n
  求0~9十个数的全排列中的第n个(第1个为0123456789)。
输入格式
  一行,包含一个整数n
输出格式
  一行,包含一组10个数字的全排列
样例输入
1
样例输出
0123456789
数据规模和约定
  0 < n <= 10!


第一次写的代码如下:(枚举法,60分,运行超时)

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		long n = scanner.nextInt();
		long cnt=0;
		flag:
		for(int a=0;a<=9;a++){
			for(int b=0;b<=9;b++){
				for(int c=0;c<=9;c++){
					for(int d=0;d<=9;d++){
						for(int e=0;e<=9;e++){
							for(int f=0;f<=9;f++){
								for(int g=0;g<=9;g++){
									for(int h=0;h<=9;h++){
										for(int i=0;i<=9;i++){
											for(int j=0;j<=9;j++){
												if(a!=b&&a!=c&&a!=d&&a!=e&&a!=f&&a!=g&&a!=h&&a!=i&&a!=j&&
														b!=c&&b!=d&&b!=e&&b!=f&&b!=g&&b!=h&&b!=i&&b!=j&&
														c!=d&&c!=e&&c!=f&&c!=g&&c!=h&&c!=i&&c!=j&&
														d!=e&&d!=f&&d!=g&&d!=h&&d!=i&&d!=j&&
														e!=f&&e!=g&&e!=h&&e!=i&&e!=j&&
														f!=g&&f!=h&&f!=i&&f!=j&&
														g!=h&&g!=i&&g!=j&&
														h!=i&&h!=j&&
														i!=j){
													cnt++;
													if(cnt==n){
														System.out.printf("%d%d%d%d%d%d%d%d%d%d\n",a,b,c,d,e,f,g,h,i,j);
														break flag;
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
}



深度优先搜索 DFS

转载于:http://rapheal.iteye.com/blog/1526863

深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底这种尽量往深处走的概念即是深度优先的概念。


举例

给出如图3-1所示的图,求图中的V0出发,是否存在一条路径长度为4的搜索路径。


 

3-1

显然,我们知道是有这样一个解的:V0->V3->V5->V6。

处理过程:

/**
 * DFS核心伪代码
 * 前置条件是visit数组全部设置成false
 * @param n 当前开始搜索的节点
 * @param d 当前到达的深度,也即是路径长度
 * @return 是否有解
 */
bool DFS(Node n, int d){
	if (d == 4){//路径长度为返回true,表示此次搜索有解
		return true;
	}

	for (Node nextNode in n){//遍历跟节点n相邻的节点nextNode,
		if (!visit[nextNode]){//未访问过的节点才能继续搜索

			//例如搜索到V1了,那么V1要设置成已访问
			visit[nextNode] = true;

			//接下来要从V1开始继续访问了,路径长度当然要加

			if (DFS(nextNode, d+1)){//如果搜索出有解
				//例如到了V6,找到解了,你必须一层一层递归的告诉上层已经找到解
				return true;
			}

			//重新设置成未访问,因为它有可能出现在下一次搜索的别的路径中
			visit[nextNode] = false;

		}
		//到这里,发现本次搜索还没找到解,那就要从当前节点的下一个节点开始搜索。
	}
	return false;//本次搜索无解
}


第二次写的代码如下:

import java.util.Scanner;

public class Main {
	
	private static int[] arr = new int[10];
	private static boolean[] hasVisited = new boolean[10];
	private static int n;
	private static int count=0;
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		dfs(0);
	}
	
	private static void dfs(int pos) {
		if(pos==10){//全排列到了长度为10,要进行判别
			count++;
			if(count==n){
				for(int i=0;i<10;i++){
					System.out.print(arr[i]);
				}
			}
		}
		for(int i=0;i<=9;i++){//首位为i
			if(!hasVisited[i]){//如果还没被访问才可以继续搜索
				arr[pos]=i;
				hasVisited[i]=true;//第i个进行访问,则设置已访问
				dfs(pos+1);//一位一位地搜索
				hasVisited[i]=false;//重新设置未访问,因为它有可能出现在下一次全排列当中
			}
		}
	}
	
}
简单的来说,就是为visit数组先要全部定义为false,然后判断是否被访问了,如果没被访问,则访问。然后设置visit数组为true,然后进行下一位的搜索,然后再设置为false,重新设置未访问。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值