练习2 24题

来源:互联网 发布:java未来五年发展前景 编辑:程序博客网 时间:2024/06/07 17:23

题目: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 (&lt;=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. <br>
 

Input
The input contains multiple test cases.<br>Each test case include, first two integers n, P. (1<n<=1000, 1<p<=10000). <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 5<br>1 3 2<br>3 6<br>1 3 2<br>4 100<br>1 2 3 2<br>
 

Sample Output
1<br>3<br>2<br>1 3<br>1 2<br><br>1<br>3<br>2<br>1 3<br>1 2<br><br>1<br>2<br>3<br>1 2<br>1 3<br>2 3<br>2 2<br>1 2 3<br>1 2 2<br><br><br><div style='font-family:Times New Roman;font-size:14px;background-color:F4FBFF;border:#B7CBFF 1px dashed;padding:6px'><div style='font-family:Arial;font-weight:bold;color:#7CA9ED;border-bottom:#B7CBFF 1px dashed'><i>Hint</i></div>Hint : You must make sure each subsequence in the subsequences is unique.</div>
 


思路:

重判,这里有两个重判,第一个重判是判断如果搜索的是子序列的第一个元素,那么判断从原始序列开始到当前位置是否已经出现过该元素,若出现过则之前肯定搜索过该元素,则放弃该元素的搜索。第二个重判,当搜索的不是子序列的第一个元素时,则判断子序列的前一个元素对应原始序列的位置,然后从该位置下一个元素开始到到当前搜索的位置之前判断该元素是否出现过,如果出现过,说明该子串出现过重复的,则放弃该元素。
技巧二:剪枝,这里的一个剪枝技巧是做了一个标记位flag,假如我在搜索长度为3的子串时,发现没有一个符合的,那么就不可能存在长度为4的子串符合条件。如果没有这个剪枝就会超时。。。。。。。。。。。。。。。。。。。。。。。。。。。



#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;
}
0 0
原创粉丝点击