【HDU】2610 Sequence one

2 篇文章 0 订阅

Sequence one

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 526    Accepted Submission(s): 198


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<n<=1000, 1<p<=10000).
 

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
Hint
Hint : You must make sure each subsequence in the subsequences is unique.
 题解:这一题题目意思有点难懂,大意是要你找到前P个子串,每个子串都需要是不下降子串(数字不递减),而子串间的大小又是由子串长度和子串中每个数字在原来串中的位置决定的。很明显这一题要剪枝(题目都说了When you want to solve a problem by using the search method, try to cut is very important......)1000的长度裸搜肯定过不了,所以想到如下剪枝:
1、所选的数不能大于前一个数。
2、前缀相同时,同一位置,同一个数仅仅搜一次。
3、在搜位置为i时,如果后面剩下数的个数小于我需要的个数,直接返回。
4、如果长度为i的序列搜不到解,那么比他长的序列也肯定搜不到(感觉这个是最重要的)
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int n,p,a[1005],sta[1005],h,ans;
bool vis[1005],f;

void finish()
{
    for (int i=0;i<h-1;i++) printf("%d ",sta[i]);
    printf("%d\n",sta[h-1]);
    ans++;
}

bool check(int last,int d,int x,int p)
{
    return  x>=last && !vis[p];
}

void dfs(int last,int lastp,int d,int l)
{
    if (n-lastp<l-d) return;
    bool flag[1005];
    memset(flag,0,sizeof(flag));
    if (d==l)
    {
        finish(); f=1;
        return ;
    }
    for (int i=lastp+1;i<=n;i++) if (check(last,d,a[i],i) && !flag[a[i]])
    {
        sta[h++]=a[i]; flag[a[i]]=1; vis[i]=1;
        dfs(a[i],i,d+1,l);
        if (ans==p) return;
        sta[--h]=0; vis[i]=0;
    }
}

int main()
{
    while (scanf("%d%d",&n,&p)!=EOF)
    {
        ans=0;
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int l=1;l<=n-1;l++)
        {
            f=0;
            memset(vis,0,sizeof(vis));
            memset(sta,0,sizeof(sta)); h=0;
            dfs(0,0,0,l);
            if (!f) break;
            if (ans==p) break;
        }
        printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值