SOJ 1027

SOJ 1027: Lotto http://acm.scu.edu.cn/soj/problem.action?id=1027

题意非常简单:给定一个序列,按字典序输出固定长度的所有子序列。标准的做法是回溯,因为题目中给出了固定长度为6,所以可以用6层循环暴力输出,代码如下:

#include <stdio.h>
int main()
{
    int num;
    while(scanf("%d",&num)==1)
    {
        if(num==0)
            return 0;
        int i,j,k,l,m,n;
        int s[14];
        for(i=0;i<num;i++)
            scanf("%d",&s[i]);
        for(i=0;i<num;i++)
            for(j=i+1;j<num;j++)
                for(k=j+1;k<num;k++)
                    for(l=k+1;l<num;l++)
                        for(m=l+1;m<num;m++)
                            for(n=m+1;n<num;n++)
                            {
                                printf("%d %d %d %d %d %d\n",s[i],s[j],s[k],s[l],s[m],s[n]);
                            }
                            printf("\n");
    }
    return 0;
}
View Code

上述方法在变化的长度情况下就不能用了,这里介绍回溯算法。不像DFS,把树遍历一遍就可以,这里需要输出所有从根结点到叶结点的路径,所以需要一个数组记录每一条从根结点到叶结点的路径,代码如下:

#include <iostream>
using namespace std;
int *num;
int *temp;
void f(int str, int rem, int k,int con)
{
    int i, j;
    if (rem > 0)
        for (i = str; i <= k - rem; i++)
        {
        temp[con-rem] = num[i];
        f(i + 1, rem-1, k,con);
        } 
    else
    {
        for (j = 0; j < con; j++)
            printf("%d ",temp[j]);
        printf("\n");
    }
}
int main()
{
    int k;
    int i;
    int con = 6;
    temp = new int[con + 1];
    while (scanf("%d", &k) == 1 && k)
    {
        num = new int[k + 1];
        for (i = 0; i < k; i++)
            scanf("%d", &num[i]);
        f(0, con, k,con);
        printf("\n");
    }
    return 0;
}
View Code

posted on 2019-03-01 12:54  小叶子曰  阅读(83)  评论(0编辑  收藏  举报

导航