1024 Sequence one

来源:互联网 发布:数据可视化 sql 编辑:程序博客网 时间:2024/06/18 04:24

1024 Sequence one

题意:对于给定序列,找到指定个数子序列,如果全部子序列少于给定个数,输出全部的子序列。子序列元素按递增顺序,输出按子序列长度及位置。

思路:根据子串长度搜索,保存上一次选择的数和所选的数的下标,当选择下一个数的时候和上次所选择的数比较大小,大于等于的符合条件,符合条件的输出。

对于每一个元素,如果是子序列的第一个元素,那么判断在原序列中,该位置之前是否出现过该元素,若出现过则放弃该元素。如果不是子序列的第一个元素,判断子序列前一个位置在原序列中原始下标,到该元素是否出现过,如果出现则放弃。

感想:题意都一直没有明白,始终不清楚子序列的选择原则,无奈啊!找题解研究了半天,终于有了眉目。

#include<iostream>

#include<stdio.h>

#include<algorithm>

using namespace std;

int n,p,l,cnt;  //搜索长度,cnt记录子串个数

int num[1001];

//做一个标记,如果一个短的串都不能够找到,

//那么就长的串就更不可能找到了,这里的一个巧妙地剪枝如果没用就会超时

bool flag;

struct Temp{

  int n,pos;

};

Temp tem[1001];

//检查产生序列前一个数字到当前数字num[t]是否出现该数

bool check(int q,int t){

   for(int i=q+1;i<t;i++)

       if(num[i]==num[t])  return false;

       return true;

}

void output(int len){

   for(int i=0;i<len-1;i++)

       cout<<tem[i].n<<" ";

   cout<<tem[len-1].n<<endl;

}

//dep搜索的深度,即目前搜索到子串的长度

//当前搜索位置

void dfs(int dep,int pos){

   if(cnt>=p) return ; //搜索到了

   if(dep==l){     //已经搜索到符合题目要求的子串个数

       cnt++;

       flag=true;

       output(l);

       return ;

    }

   for(int i=pos;i<n;i++){

       if(dep!=0&&tem[dep-1].n<=num[i]||dep==0)   //tem[dep-1].n上一节点选中的数字

       {

           if((dep!=0&&tem[dep-1].n<=num[i])||dep==0)

           {

               if(dep==0&&!check(-1,i)) continue;

               if(dep!=0&&!check(tem[dep-1].pos,i)) continue;

                tem[dep].n=num[i];

                tem[dep].pos=i;

                dfs(dep+1,i+1);

           }

       }

    }

   return ;

}

int main(){

   while(cin>>n>>p){

       for(int i=0;i<n;i++)

           cin>>num[i];

       cnt=0;

       for(int i=1;i<n;i++){

           flag=false;

           l=i;

           dfs(0,0);

           if(cnt>=p||!flag) break;    //!flag子串不合适,那么直接退出

       }

       cout<<endl;

    }

   return 0;

}

0 0