1. 程式人生 > >nyoj 19 擅長排列的小明 【全排列(n中抽取m個數)】

nyoj 19 擅長排列的小明 【全排列(n中抽取m個數)】

擅長排列的小明

時間限制:1000 ms  |  記憶體限制:65535 KB 難度:4
描述
小明十分聰明,而且十分擅長排列計算。比如給小明一個數字5,他能立刻給出1-5按字典序的全排列,如果你想為難他,在這5個數字中選出幾個數字讓他繼續全排列,那麼你就錯了,他同樣的很擅長。現在需要你寫一個程式來驗證擅長排列的小明到底對不對。
輸入
第一行輸入整數N(1<N<10)表示多少組測試資料,
每組測試資料第一行兩個整數 n m (1<n<9,0<m<=n)
輸出
在1-n中選取m個字元進行全排列,按字典序全部輸出,每種排列佔一行,每組資料間不需分界。如樣例
樣例輸入
2
3 1
4 2
樣例輸出
1
2
3
12
13
14
21
23
24
31
32
34
41
42
43
來源
上傳者

思路:

          以1-n開始為第一個數開始遍歷,然後進行遞迴賦值第二個數,輸出,直至到n結束迴圈!

程式碼:

//從1開始遞迴,然後看看是否滿足m個數,如果滿足兩個數,那麼就將這兩個數
//輸出,然後繼續進行賦值遞迴,直到所有的數輸出結束之後,然後vis[i]就也都是0了
//然後從第二個開始為起始數字,進行找第二個數(進行遞迴查詢),找到就輸出,一直這樣
//查詢,直到查詢結束為止! 
#include <stdio.h>
#include <string.h>
int n,m;
int vis[10];
int a[10];
void dfs(int num)
{
	if(num==m)//和對n個數進行全排列差別就是將這的n換成m,每次排列滿足m個數就輸出! 
	{
		for(int i=0;i<m;i++)
		{
			printf("%d",a[i]);
		}
		printf("\n");
		return; 
	}
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			a[num]=i;
			dfs(num+1);//每次輸出一次,就會取消一次標記,然後繼續進行迴圈,為陣列a賦值 
			vis[i]=0;//然後繼續進行遞迴,看是否滿足m==n,如果不滿足,繼續遞迴賦值,直到滿足條件,進行輸出為止 
		}
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		memset(vis,0,sizeof(vis));
		dfs(0);
	}
	return 0;
}