算法提高 排列数
时间限制:1.0s 内存限制:256.0MB
问题描述
0、1、2三个数字的全排列有六种,按照字母序排列如下:
012、021、102、120、201、210
输入一个数n
求0~9十个数的全排列中的第n个(第1个为0123456789)。
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,重新设置未访问。