SOJ 1027
SOJ 1027: Lotto http://acm.scu.edu.cn/soj/problem.action?id=1027
题意非常简单:给定一个序列,按字典序输出固定长度的所有子序列。标准的做法是回溯,因为题目中给出了固定长度为6,所以可以用6层循环暴力输出,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
上述方法在变化的长度情况下就不能用了,这里介绍回溯算法。不像DFS,把树遍历一遍就可以,这里需要输出所有从根结点到叶结点的路径,所以需要一个数组记录每一条从根结点到叶结点的路径,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }