天天看點

排列組合模闆小結

1.dfs回溯法輸出組合
           
#include<iostream> 
#include<cmath> 
#include<cstring> 
#include<algorithm> 
using namespace std;
int visit[1005],a[1005];
int n,m;//表示從n個數中取m個數
void dfs(int x,int y)//x表示目前選的數是n個中的第x個,y表示遞歸的層數即選的第m個數
{
	if(y==m)     
	{
		for(int i=0;i<n;i++)
		{
			if(visit[i])
			cout<<a[i]<<" ";
		}
		cout<<endl;
		return;
	}
	else 
		for(int j=x;j<n;j++)
		{
			if(!visit[j])
			{
				visit[j]=1;
				dfs(j+1,y+1);
				visit[j]=0;   //回溯,傳回上一層标記為未選    
		} 
}

int main()
{
	int i,j,k;
	while(cin>>n>>m)
	{
		for(i=0;i<n;i++)
		cin>>a[i];
	memset(visit,0,sizeof(visit));
		dfs(0,0);
	}
}
           

2.用STL的next_permutation輸出全排列

#include<iostream> 
#include<cmath> 
#include<cstring> 
#include<algorithm> 
using namespace std;
int main()
{
	int i,j,k;
	while(cin>>k)
	{
		int a[105];
		for(i=0;i<k;i++)
			cin>>a[i];
		sort(a,a+k);
		do
		{
			for(i=0;i<k;i++)
				cout<<a[i]<<" ";
			cout<<endl;
		}
		while(next_permutation(a,a+k));
	}
}
           

題目: http://poj.org/problem?id=2245

下面是一道練習題

Accept: 428    Submit: 986

Time Limit: 1000 mSec    Memory Limit : 65536 KB

排列組合模闆小結
Problem Description

In the German Lotto you have to select 6 numbers from the set {1,2,...,49}.

A popular strategy to play Lotto - although it doesn't increase your chance of winning - is to select a subset S containing k (k>6) of these 49 numbers, and then play several games with choosing numbers only from S.

For example, for k=8 and S = 1,2,3,5,8,13,21,34 there are 28 possible games: [1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2,3,5,13,21], ..., [3,5,8,13,21,34].

Your job is to write a program that reads in the number k and the set S and then prints all possible games choosing numbers only from S.

排列組合模闆小結
Input

The input file will contain one or more test cases.

Each test case consists of one line containing several integers separated from each other by spaces. The first integer on the line will be the number k (6 < k < 13). Then k integers, specifying the set S, will follow in ascending order.

Input will be terminated by a value of zero (0) for k.

排列組合模闆小結
Output

For each test case, print all possible games, each game on one line.

The numbers of each game have to be sorted in ascending order and separated from each other by exactly one space. The games themselves have to be sorted lexicographically, that means sorted by the lowest number first, then by the second lowest and so on, as demonstrated in the sample output below.

The test cases have to be separated from each other by exactly one blank line. Do not put a blank line after the last test case.

排列組合模闆小結
Sample Input

7 1 2 3 4 5 6 78 1 2 3 5 8 13 21 340

排列組合模闆小結
Sample Output

1 2 3 4 5 61 2 3 4 5 71 2 3 4 6 71 2 3 5 6 71 2 4 5 6 71 3 4 5 6 72 3 4 5 6 71 2 3 5 8 131 2 3 5 8 211 2 3 5 8 341 2 3 5 13 211 2 3 5 13 341 2 3 5 21 341 2 3 8 13 211 2 3 8 13 341 2 3 8 21 341 2 3 13 21 341 2 5 8 13 211 2 5 8 13 341 2 5 8 21 341 2 5 13 21 341 2 8 13 21 341 3 5 8 13 211 3 5 8 13 341 3 5 8 21 341 3 5 13 21 341 3 8 13 21 341 5 8 13 21 342 3 5 8 13 212 3 5 8 13 342 3 5 8 21 342 3 5 13 21 342 3 8 13 21 342 5 8 13 21 343 5 8 13 21 34 

把模闆變一下,不過這倒題的輸出實在是太坑了

#include<iostream> 
#include<cmath> 
#include<cstring> 
#include<algorithm> 
using namespace std;
int visit[1005],a[1005];
int n,m;
void dfs(int x,int y)
{
	if(y==6)
	{
		int first=1;
		for(int i=0;i<n;i++)
		{
			if(visit[i])
			{
				if(first==1)
				{cout<<a[i];first=0;}
				else
			    cout<<" "<<a[i];
			}
		}
		cout<<endl;
		return;
	}
	else 
		for(int j=x;j<n;j++)
		{
			if(!visit[j])
			{
				visit[j]=1;
				dfs(j+1,y+1);
				visit[j]=0;
			}    
		} 
}

int main()
{
	int i,j,k;
	int first=1;
	while(cin>>n&&n)
	{
		for(i=0;i<n;i++)
		cin>>a[i];
		if(first==1)first=0;
		else cout<<endl;
	memset(visit,0,sizeof(visit));
		dfs(0,0);
	}
}
           

繼續閱讀