Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342913
  • 博文数量: 122
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 1191
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 11:12
文章分类

全部博文(122)

文章存档

2010年(122)

我的朋友

分类: C/C++

2010-04-09 01:55:35

一、问题描述

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 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 7

8 1 2 3 5 8 13 21 34

0

Sample Output

1 2 3 4 5 6

1 2 3 4 5 7

1 2 3 4 6 7

1 2 3 5 6 7

1 2 4 5 6 7

1 3 4 5 6 7

2 3 4 5 6 7

 

1 2 3 5 8 13

1 2 3 5 8 21

1 2 3 5 8 34

1 2 3 5 13 21

1 2 3 5 13 34

1 2 3 5 21 34

1 2 3 8 13 21

1 2 3 8 13 34

1 2 3 8 21 34

1 2 3 13 21 34

1 2 5 8 13 21

1 2 5 8 13 34

1 2 5 8 21 34

1 2 5 13 21 34

1 2 8 13 21 34

1 3 5 8 13 21

1 3 5 8 13 34

1 3 5 8 21 34

1 3 5 13 21 34

1 3 8 13 21 34

1 5 8 13 21 34

2 3 5 8 13 21

2 3 5 8 13 34

2 3 5 8 21 34

2 3 5 13 21 34

2 3 8 13 21 34

2 5 8 13 21 34

3 5 8 13 21 34

 

二、解题思路

    使用递归回溯进行求解,backtrace(int n,int s)表示从数组的第s个开始取第n个,实际是取到的第t个,那么取n+1个就应该从第t+1个开始取。

三、代码

#include<iostream>
using namespace std;
int N;        //子集的大小
int a[14];    //输入子集
bool b[14];    //是否已经取掉了
int M;        //要输出的行数
int sum;    //已经输出的行数
//在n个中取m个有多少种取法
int C(int n,int m)
{
    int a=1;
    int b=1;
    if(m>n/2)
        m=n-m;
    for(int i=0;i<m;++i)
    {
        a*=(n-i);
        if((a%(m-i))==0)
            a/=(m-i);
        else
            b*=(m-i);
    }
    a/=b;
    return a;
}
//从s个开始取第n个
void backtrace(int n,int s)
{
    int i;
    if(sum>=M)
        return ;
    if(n==6)
    {
        int num=0;
        for(i=0;i<N;++i)
        {
            if(b[i]==true)
            {
                printf("%d",a[i]);
                num++;            
                if(num==6)
                    printf("\n");
                else
                    printf(" ");
            }
            
        }
        sum++;
    }
    else
    {
        for(i=s;i<N;++i)
        {
            if((N-i)<(6-n))
                return ;
            if(b[i]==false)
            {
                b[i]=true;
                backtrace(n+1,i+1);
                b[i]=false;
            }
        }
    }
}
int main()
{
    int i;
    scanf("%d",&N);
    while(N!=0)
    {
        for(i=0;i<N;++i)
            scanf("%d",&a[i]);
        M=C(N,6);
        sum=0;
        memset(b,0,sizeof(b));
        backtrace(0,0);
        printf("\n");
        scanf("%d",&N);
    }
    return 0;
}


阅读(785) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~