专题二 1024

一. 题目编号

专题二 1024

Sequence one

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.
Now give you a number sequence, include n (<=1000) 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 sequence of each integer’s position in the initial sequence. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {3}; {2}; {1,3}; {1,2}. {1,3} is first than {1,2} because the sequence of each integer’s position in the initial sequence are {1,2} and {1,3}. {1,2} is smaller than {1,3}. If you also can not understand , please see the sample carefully.

Input

The input contains multiple test cases.
Each test case include, first two integers n, P. (1

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 5
1 3 2

3 6
1 3 2

4 100
1 2 3 2

Sample Output

1
3
2
1 3
1 2

1
3
2
1 3
1 2

1
2
3
1 2
1 3
2 3
2 2
1 2 3
1 2 2

You must make sure each subsequence in the subsequences is unique.

二. 简单题意

有一个数列N,和一个数字k,输出该数列的前k个子序列,如果k大于N的所有子序列,输出所有符合要求的序列,序列要求不能是递减序列
在给定的序列中找到固定个数的递增的子序列,如果子序列的总个数少于要求的个数,那么就把所有的子序列输出即可。

三. 解题思路形成过程

dfs搜索,保存上一次选择的数和所选的数的下标,当选择下一个数的时候比较和上次所选择数的大小,大于等于的是符合条件的,符合条件的输出。

  1. 判重:
    ①当我们搜索子序列的第一个元素的时候,只需要和该元素之前的比较,如果有重复的话不再搜索
    ②当我们搜索子序列的第i个元素的时候,将要比较的元素j与 (搜到的子序列中第i-1个元素, 元素j)这个开区间的元素比较,如果有重复的话不再搜索
  2. 剪枝:
    flag作为一个标记,每次搜索长度为i的子序列的时候将其赋值为false,找到一个长为i的子序列就赋值为true。
    试想,如果长为i的子序列都不曾找到,那么一定不会存在长为i+1的子序列的。

主要参考这里的代码,虽然还不是很懂

一个有效的剪枝,一个子串如果不成立,那么比其大的子串显然不成立,所以剪枝。

四. 感想

题目没怎么看懂,又看了别人的博客看了好多还不是很理解。
个人能力还需加强~

五. AC代码

#include <iostream>
#include <algorithm>
using namespace std;
int n,p,len,count_num;
int num[1001];
bool flag;
 struct Tem
{
    int n,pos;
};
Tem tem[1001];
bool check(int s,int e)
{
    for(int i = s+1; i < e; i++)
    if(num[i]==num[e])
    return false;
    return true;
}

void print_sequence(int length)
{
    for(int i = 0; i < length-1;i++)
    cout<<tem[i].n<<" ";
    cout<<tem[length-1].n<<endl;
}
void dfs(int dep,int pos)
{
    if(count_num >= p)return;
    if(dep==len)
    {
        count_num++;
        flag = true;
        print_sequence(len);
        return;
    }
    for(int i=pos;i<n;i++)
    {
        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];
        count_num = 0;
        for(int i = 1;i < n;i++)
        {
            flag=false;
            len = i;
            dfs(0,0);
            if(count_num>=p||!flag)break;
        }
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值