题意:给出一个序列,要你输出这个序列的前p个序列(若总排列w<p,则只需要输出w个)
排列方式:
序列为原序列的非减子序列,
length从小到大,
length相同的话,位置前的排在前面;
思路:判断如果搜索的是子序列的第一个元素,那么判断从原始序列开始到当前位置是否已经出现过该元素,若出现过则之前肯定搜索过该元素,则放弃该元素的搜索。第二个重判,当搜索的不是子序列的第一个元素时,则判断子序列的前一个元素对应原始序列的位置,然后从该位置下一个元素开始到到当前搜索的位置之前判断该元素是否出现过,如果出现过,说明该子串出现过重复的,则放弃该元素。
#include<iostream>
#include<set>
#include<cstring>
#define LL long long
using namespace std;
const int maxn=1010;
LL a[maxn];
LL ans[10000];
int n,p,len;
bool flag;
set<LL>ssss;
set<LL>::iterator it;
void dfs(int cur,int cnt)
{
if(cnt>len)
return ;
ans[cnt]=a[cur];
if(cnt==len)
{
for(int i=1;i<cnt;i++)
cout<<ans[i]<<" ";
cout<<ans[cnt]<<endl;
flag=true;
p--;
return ;
}
//开始这个set是写在了函数外面,然后一直wa
//写在外面,dfs操作的其实一直是同一个s,前面的可能也会被clear()
set<LL>s;
s.clear();
for(int i=cur+1;i<=n;i++)
{
if(a[i]>=a[cur]&&p>0)
{
it=s.find(a[i]);
if(it!=s.end())
continue;
dfs(i,cnt+1);
s.insert(a[i]);
}
}
}
int main()
{
while(cin>>n>>p)
{
for(int i=1;i<=n;i++)
cin>>a[i];
int m=0; ssss.clear();
for(int i=1;i<=n;i++)
{
it=ssss.find(a[i]);
if(it!=ssss.end())
continue;
cout<<a[i]<<endl;
ssss.insert(a[i]);
m++;
if(m>=p)
break;
}
p-=m;
len=2;
ssss.clear();
while(p>0&&len<=n)
{
flag=false;
ssss.clear();
for(int i=1;i<=(n-len+1);i++)
{
it=ssss.find(a[i]);
if(it!=ssss.end())
continue;
dfs(i,1);
ssss.insert(a[i]);
}
if(!flag)
break;
len++;
}
cout<<endl;
}
return 0;
}