hdu 2611 Sequence two(深搜)

简介:

Sequence two

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 98 Accepted Submission(s): 46

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 (<=100) 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 subsequence by lexicographical. For example initial sequence 1 3 2 the total legal subsequences is 5. According to order is {1}; {2}; {3}; {1,2}; {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<=100, 1<p<=100000).
 

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

1
2
3
1 2
1 3

1
2
3
1 2
1 3
2 2
2 3
1 2 2
1 2 3
Hint
Hint : You must make sure each subsequence in the subsequences is unique
分析:
(1)这道题和前一题sequence one 属于一类题,都是dfs,这里主要是首先排一次顺序,然后再检查时注意输入时的下标,生成的子串不能够出现下表非递增的,也就是首先子串时递增的,其次下标也是递增的,然后不能有重复的子串出现。
(2)这是我的代码,和前一题的代码有稍微的改动,无奈一直wrong。。。。。。。。。。。。哪位研究这一题的看到了,帮忙找找错。。。。。。。。。
 
复制代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

//len:搜索的长度,count:记录有多少个串了
int n,p,len,count_num,pre;

//做一个标记,如果一个短的串都不能够找到,
//那么就长的串就更不可能找到了,这里的一个巧妙地剪枝如果没用就会超时
bool flag;

typedef struct
{
    int n,pos;
    int ind;
}Tem;

Tem tem[1001];
Tem num[1001];

bool cmp(Tem a,Tem b)
{
    if(a.n==b.n)
    return a.pos<b.pos;
    return a.n<b.n;
}
//若在产生序列的前一个数字到当前这个数字中,
//出现等于num[e]的,那么说明之前已经有序列选择了num[e],
bool check(int s,int e)
{
    for(int i = e-1; i > s; i--)
    if(num[i].n==num[e].n)return false;
    return true;
}


void print_sequence(int length)
{
    for(int i = 0; i < length-1;i++)
    printf("%d ",tem[i].n);
    printf("%d\n",tem[length-1].n);
}

//dep:搜索的深度,也就是目前搜索到子串的长度
//pos: 当前搜索的位置
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&&num[i].pos>tem[dep-1].pos)||dep==0)
        {
            if(dep==0&&!check(-1,i))
            continue;
            if(dep!=0&&!check(tem[dep-1].ind,i))
            continue;
            tem[dep].n = num[i].n;
            tem[dep].pos = num[i].pos;
            tem[dep].ind = i;
            dfs(dep+1,i+1);
        }
    }
    return;
}

int main()
{
    while(scanf("%d%d",&n,&p)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&num[i].n);
            num[i].pos = i;
        }

        sort(num,num+n,cmp);
        count_num = 0;
        for(int i = 1;i < n;i++)
        {
            flag=false;
            pre = 0;
            len = i;
            dfs(0,0);
            if(count_num>=p||!flag)break;
        }
        printf("\n");
    }
    return 0;
}
复制代码

 

这是我从网上找到达一个可以通过的代码。。。。。。

思路一样。。。。。。。求解释。。。。。。。

复制代码
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>

using namespace std;

int n,p;

struct Node
{
        int pos;
        int v;
};

int cont;
Node a[110];
int res[10001];
int deep;

bool mcmp(const Node& x,const Node& y)
{
        if(x.v != y.v)
                return x.v < y.v;
        else
                return x.pos < y.pos;
};

void init()
{
        int i;
        int tv;
        cont = 0;
        Node tnode;
        for(i = 1;i <= n;i ++)
        {
                scanf("%d",&tv);
                a[i].pos = i;// 把位置作为结构题的一项
                a[i].v = tv;
        }
        sort(a+1,a+1+n,mcmp);//按照值的大小重排序
}

bool dfs(int dep,int sp,int pp)//deepth ,search position , previous position
{
        int i;
        int prev;
        bool f = false;
        if(dep == deep+1)
        {
                cont ++;
                for(i = 1;i < dep;i ++)
                        printf(i == deep ? "%d\n" : "%d ",res[i]);
                if(cont == p) return true;
                return false;
        }

        if(sp > n ) return false;

        for(i = sp;i <= n;i ++)
        {
                if(a[i].pos > pp)
                {
                        if(!f) { f = true; prev = a[i].v;} // 判重
                        else        if(prev == a[i].v) continue;//判重
                        prev = a[i].v;
                        res[dep] = a[i].v;
                        if(dfs(dep+1,i+1,a[i].pos) ) return true;

                }
        }
        return false;
}

void work()
{
        int i,j;
        for(i = 1;i <= n;i ++)
        {
                deep = i;
                if(dfs(1,1,0)) return ;
        }
}

int main()
{
        while(scanf("%d%d",&n,&p) != EOF)
        {
                init();
                work();
                printf("\n");
        }

        return 0;
}
复制代码












本文转自NewPanderKing51CTO博客,原文链接:  http://www.cnblogs.com/newpanderking/archive/2012/10/11/2720238.html ,如需转载请自行联系原作者

相关文章
|
9月前
|
存储
poj 3254 Corn Fields (状态压缩dp)
状态压缩dp其实就是用二进制来表示所有的状态,比如这题, 我们在某一行可以这样取0 1 0 1 1 0 1,用1代表取了,0代表没取,因为这点,它的数据量也限制在20以内,所有看到这样数据量的题目可以先考虑一下状态压缩dp。对于有多行的数据,所有状态的总数必然很庞大,而且不用特殊的方法想要存储这些状态是不太现实的。既然每个点只有这两种情况,我们可以用二进制的一位来表示,0 1 0 1 1 0 1就可以表示为二进制0101101也就是十进制的45,如果我们想要枚举6个点的所有状态,我们只需要从0到2^6取其二进制就可以了,并不会重复或是多余。
19 0
|
9月前
华为机试HJ44:Sudoku(数独问题,深度优先遍历DFS解法)
华为机试HJ44:Sudoku(数独问题,深度优先遍历DFS解法)
|
7月前
|
算法 测试技术
每日一题:LeetCode-LCR 143.子结构判断
每日一题:LeetCode-LCR 143.子结构判断
|
9月前
|
人工智能
poj 2299 Ultra-QuickSort 求逆序数 树状数组解法
所谓离散化,我们的了解就是对原数组排序,然后用所在位置的下标代替原数,这样我们就可以把数据范围缩小到1-500000,这个数组是开的下的。
25 0
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
125 0
HDU-1213,How Many Tables(并查集水题)
HDU-1213,How Many Tables(并查集水题)
|
C语言
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
HDOJ/HDU Tempter of the Bone(深搜+奇偶性剪枝)
85 0
td_
HDU_5952 Counting Cliques 深搜回溯
题意 HDU5952—16年沈阳E题给定一个无向图,输出图中节点个数为 s 的完全图的个数 思路 暴力深搜回溯,要点在于搜索时需要让当前点大于已经搜过的点,以此来去重,比如 1-3-5-4 这个完全图在之前必定可以搜出来 1-3-4-5,并且当前点要与之前的点保证有路,这样搜出来才是完全图做的时.
td_
1079 0