hdu2611Sequence two(dfs)

来源:互联网 发布:菜鸟网络校园加盟条件 编辑:程序博客网 时间:2024/04/23 16:43

->题目单击这<-

题目大意:跟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;}//187MS336K/*3 51 3 23 61 3 24 1001 2 3 25 201 2 3 2 35 201 2 3 4 25 41 2 3 2 35 101 2 3 4 55 105 4 3 2 1*/
PS:本题改完后提交各种哇,后来在sort函数的cmp函数里面把下标比较加上才过了,还是因为不了解STL函数的内部机制,不知道cmp函数是如何工作的,原以为直接对内容排序即可,排完序的序列下标应该是递增的,此题说明并非如此,如有大牛路过,还请不吝赐教,弱菜感激不尽。

原创粉丝点击