hdu2611Sequence two(dfs)

->题目单击这<-

题目大意:跟2610基本一样,就不多说了,唯一的区别是输出部分,2610输出要求按子串中数字出现的位置靠前的先输出,本题则要求按子串的逻辑顺序输出,即先输出短的,长度相同的子串按第一个不相同的数的大小升序输出。2610按出现的位置输出,直接在原串上搜索就可以了,先搜到的一定是位置靠前的。但本题要求从小到大输出,所以很容易想到要对原数组排序,在排好序的数组里面搜,结果就一定满足输出要求,因为排完序后先搜到的一定是小的。但是这样会出现问题,因为排完序后会搜到许多错误的子串,在原串中不满足要求的,一排序就能满足不递减了,所以2610的2个判重也是要加上的,最后判断一下,搜到的子串在原数组中的下标是否也是递增的,如果是就是合法的,输出之,否则不合法,弃之。本题还需要注意的问题是第二种判重(见2610题解),在判重的时候不能在排好序的数组中判重,应该在原数组中遍历,看是否已经出现过当前数字,因为你在排好序的数组中这样判重的话,会把一些合法的答案弃掉了。

比如原序列1 2 3 2 3  排好序后是1 2 2 3 3,现在搜长度为4的子串,已搜1 2 2 ,现在搜第四个3,发现第四个数3在原数组中的位置是3 < 第3个数2在原数组中的位置4,不合法,弃之,然后搜第5个3,现在执行第二种判重,如果在排好序的数组中判重的话,就会发现第四个位置有了3,于是也会放弃这组,而实际情况是,1 2 2 3 是合法的!所以要在第三个2在原数组的位置4开始,到第五个数3在原数组的位置5之间看有没有3出现,显然是没有的,所以1 2 2 3 合法。

这样把2610的代码稍做改动就可以过这个题了,基本一样的。详情请见代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct node
{
    int id,num;
}lcm[105];
int n,p;
int yuan[105];
int flag;
bool flag1[10000005];
int ans[105];
//int first[105],firstnum;

int cmp(struct node a,struct node b)
{
    if(a.num != b.num)//此处WA了数次!!!
        return a.num < b.num;
    else
        return a.id < b.id;
}

/*int appear(int t)
{
    int i;
    for(i = 0;i < firstnum;i ++)
        if(first[i] == t)
            return 1;
    return 0;
}
*/
int isok(int s,int cp)
{
    if(s > cp)
        return 0;
    int i;
    for(i = s + 1;i < cp;i ++)
        if(yuan[i] == yuan[cp])
            return 0;
    return 1;
}

void dfs(int cur,int deep,int curdeep)
{
    int ii;
    if(p <= 0)
        return;
    if(curdeep == deep)
    {
        for(ii = 2;ii <= deep;ii ++)
            if(lcm[ans[ii]].id < lcm[ans[ii - 1]].id)
                return;
        p --;
        flag = 1;
        for(ii = 1;ii < deep;ii ++)
            printf("%d ",lcm[ans[ii]].num);
        printf("%d\n",lcm[ans[ii]].num);
        return;
    }
    for(ii = cur + 1;ii <= n;ii ++)
    {
        if(lcm[ii].id < lcm[cur].id)
            continue;
        if(isok(lcm[ans[curdeep]].id,lcm[ii].id))
        {
            ans[curdeep + 1] = ii;
            dfs(ii,deep,curdeep + 1);
        }
    }
}

int main()
{
    int i,j;
    while(scanf("%d%d",&n,&p) != EOF)
    {
        for(i = 1;i <= n;i ++)
        {
            scanf("%d",&lcm[i].num);
            yuan[i] = lcm[i].num;
            lcm[i].id = i;
        }
        flag = 1;
        sort(lcm + 1,lcm + 1 + n,cmp);
        for(i = 1;i <= n && flag;i ++)//搜索深度
        {
            flag = 0;//
            memset(flag1,0,sizeof(flag1));
            //firstnum = 0;
            for(j = 1;j <= n;j ++)
            {
                if(flag1[lcm[j].num] == 0)//!appear(lcm[j].num))//lcm[i].num != lcm[i - 1].num)//)
                {
                    //first[firstnum ++] = lcm[j].num;
                    flag1[lcm[j].num] = 1;
                    ans[1] = j;
                    dfs(j,i,1);
                }
            }
        }
        printf("\n");
    }
    return 0;
}
//187MS	336K
/*
3 5
1 3 2
3 6
1 3 2
4 100
1 2 3 2
5 20
1 2 3 2 3
5 20
1 2 3 4 2
5 4
1 2 3 2 3
5 10
1 2 3 4 5
5 10
5 4 3 2 1
*/
PS:本题改完后提交各种哇,后来在sort函数的cmp函数里面把下标比较加上才过了,还是因为不了解STL函数的内部机制,不知道cmp函数是如何工作的,原以为直接对内容排序即可,排完序的序列下标应该是递增的,此题说明并非如此,如有大牛路过,还请不吝赐教,弱菜感激不尽。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值