题意:
给你n个数组成一个序列,要求找出m个子序列,要求这m个子序列非递减。
输出的时候先按长度,再按每个数字的位置。。。。
转:
/*
分析:
(1)题意很简单就是在给定的序列中找到固定个数的递增的子序列,如果子序列的总个数少于要求的个数,那么就把所有的子序列输出即可,注意每组测试用例就为有一空行。
(2)技巧一:重判,这里有两个重判,第一个重判是判断如果搜索的是子序列的第一个元素,那么判断从原始序列开始到当前位置是否已经出现过该元素,若出现过则之前肯定搜索过该元素,则放弃该元素的搜索。第二个重判,当搜索的不是子序列的第一个元素时,则判断子序列的前一个元素对应原始序列的位置,然后从该位置下一个元素开始到到当前搜索的位置之前判断该元素是否出现过,如果出现过,说明该子串出现过重复的,则放弃该元素。这里的两个重判需要好好地想想,很巧妙。
(3)技巧二:剪枝,这里的一个剪枝技巧是做了一个标记位,假如我在搜索长度为3的子串时,发现没有一个符合的,那么就不可能存在长度为4的子串符合条件。如果没有这个剪枝就会超时,看来影响很大的。。。。。
*/
转自:点击打开链接
#include"stdio.h"
#include"string.h"
#define N 1001
int a[N];
int n,m;
struct node
{
int n,pos;
}A[N];
int f;
int cnt;
int len;
//上个深度找到的数的位置为s
//这个深度找到的数的位置为e
//看s+1到e-1之间是否有与位置e上的数相等的数
//如果有的话,说明e位置的数之前已经用过了,再用的话肯定重复。。。。
int fun(int s,int e)
{
int i;
for(i=s+1;i<e;i++)
if(a[i]==a[e])return 0;
return 1;
}
void print(int len)
{
int i;
for(i=0;i<len-1;i++)
printf("%d ",A[i].n);
printf("%d\n",A[i].n);
}
//depΪÉî¶È,posΪËÑË÷µÄλÖÃ
void dfs(int dep,int pos)
{
if(cnt>=m)return ;
if(dep==len)
{
f=1;
cnt++;
print(len);
return ;
}
for(int i=pos;i<n;i++)
{
if(dep==0||(dep!=0&&A[dep-1].n<=a[i]))
{
if(dep==0&&!fun(-1,i))continue;
if(dep!=0&&!fun(A[dep-1].pos,i))continue;
A[dep].n=a[i];
A[dep].pos=i;
dfs(dep+1,i+1);
}
}
return ;
}
int main()
{
int i;
while(scanf("%d%d",&n,&m)!=-1)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
cnt=0;
for(i=1;i<n;i++)
{
f=0;
len=i;
dfs(0,0);
if(cnt>=m||f==0)break;
}
printf("\n");
}
return 0;
}