Problem Description
Search is important in the acm algorithm. When you want to solve a problem by using the search method, try to cut is very important.<br>Now give you a number sequence, include n (<=100) integers, each integer not bigger than 2^31, you want to find the first P subsequences that is not decrease (if total subsequence W is smaller than P, than just give the first W subsequences). The order of subsequences is that: first order the length of the subsequence. Second order the subsequence by lexicographical. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {2}; {3}; {1,2}; {1,3}. If you also can not understand , please see the sample carefully. <br>
Input
The input contains multiple test cases.<br>Each test case include, first two integers n, P. (1<n<=100, 1<p<=100000). <br>
Output
For each test case output the sequences according to the problem description. And at the end of each case follow a empty line.
Sample Input
3 51 3 23 61 3 24 1001 2 3 2
Sample Output
1231 21 31231 21 31231 21 32 22 31 2 21 2 3
==========================
这道题目和上一道题目的不同在于:对于同长度的子集,我们要按照字典排序输出;其次我们输出的解中不应该包含原集合(即使它是合法的)。
按照字典顺序输出,我们首先想到的肯定是对原数列排序,但这样会破坏数列的原始顺序,而我们所寻找的解是与数列的初始序号有关的,所以我们用结构体来记录数据的初始编号;另外,在判重时我们也不能单单关注当前数据是否在之前出现过了,因为之前出现的数据可能因为初始编号没较小有被用过(判重的实质:放入当前数据所构成的解集合是否在之前出现过),所以我们只需要在上一题的基础上稍作修改即可,(①加入结构体记录初始编号;②修改判重函数)。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,t,sum;
int length;
bool flag;
int position[10010];
struct fc
{
int index,num;
}a[10010];
bool complare(fc x,fc y)
{
if(x.num==y.num)return x.index<y.index;
return x.num<y.num;
}
bool same(int x,int y)
{
for(int i=x+1;i<=y-1;++i)
{
if(a[y].num==a[i].num&&a[i].index>a[x].index)return 0;//与当前数相等的数据并不一定在之前构成过可行解;
}
return 1;
}
void search(int x,int start)
{
if(sum>=t)
{
return ;
}
if(x>length)
{
flag=1;
sum++;
cout<<a[position[1]].num;
for(int i=2;i<=length;++i)
cout<<" "<<a[position[i]].num;//HDU注意输出格式;
cout<<endl;
return ;
}
for(int i=start;i<=n;++i)
{
if((x==1&&same(position[x-1],i)==1)||(x!=1&&a[i].num>=a[position[x-1]].num&&same(position[x-1],i)==1&&a[i].index>a[position[x-1]].index))//是否满足初始编号;
{
position[x]=i;
search(x+1,i+1);
}
}
}
int main()
{
while(cin>>n>>t)
{
sum=0;
memset(a,0,sizeof(a));
memset(position,0,sizeof(position));
for(int i=1;i<=n;++i)
cin>>a[i].num,a[i].index=i;
sort(a+1,a+1+n,complare);//排序在两数相同时,初始编号小的数优先级高;
for(int i=1;i<n;++i)
{
length=i;
flag=0;
search(1,1);
if(!flag||sum>=t)
{
break;
}
}
cout<<endl;
}
return 0;
}