HDU 2610 (自己完全找不到思路) Sequence one

搜索虐我千百遍,我待搜索。。。好吧,我还木有初恋

题意:

我开始理解题意就理解偏了,Orz

题中有n个元素构成的序列,求出前p个非递减子序列。子序列是先按长度排序的,然后按原序列先后位置排序的。

这里的非递减是指子序列中从左到右元素大小的值不减,对,就是这我理解错了。

如果p>所有符合要求的子序列的个数,那么输出所有的子序列

 

这道题完全是参照这个大神的博客的代码A过的

http://www.cnblogs.com/newpanderking/archive/2012/10/11/2719941.html

 

思路:

按子序列的长度从1到n-1去搜,在搜长为len的子序列时,也是从左到右的元素逐个搜索,当搜索到的元素的个数满足len时,便输出一个子序列。

判重:

①当我们搜索子序列的第一个元素的时候,只需要和该元素之前的比较,如果有重复的话不再搜索

②当我们搜索子序列的第i个元素的时候,将要比较的元素j与 (搜到的子序列中第i-1个元素, 元素j)这个开区间的元素比较,如果有重复的话不再搜索

剪枝:

flag作为一个标记,每次搜索长度为i的子序列的时候将其赋值为false,找到一个长为i的子序列就赋值为true。

试想,如果长为i的子序列都不曾找到,那么一定不会存在长为i+1的子序列的。

 

再次膜拜一下高冷的代码君:

 1 #define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 struct Tem
 8 {
 9     int n, pos;
10 }tem[1010];
11 int n, p, len, cnt, num[1010];
12 bool flag;
13 
14 bool check(int s, int e)
15 {
16     for(int i = s + 1; i < e; ++i)
17         if(num[i] == num[e])
18             return false;
19     return true;
20 }
21 
22 void OutPut(int len)
23 {
24     for(int i = 0; i < len - 1; ++i)
25         printf("%d ", tem[i].n);
26     printf("%d\n", tem[len - 1].n);
27 }
28 
29 void DFS(int dep, int pos)
30 {
31     if(cnt >= p)
32         return;
33     if(dep == len)
34     {
35         ++cnt;
36         flag = true;
37         OutPut(len);
38         return;
39     }
40     for(int i = pos; i < n; ++i)
41     {
42         if(dep == 0 || tem[dep - 1].n <= num[i])
43         {
44             if(dep == 0 && !check(-1, i))
45                 continue;
46             if(dep != 0 && !check(tem[dep - 1].pos, i))
47                 continue;
48             tem[dep].n = num[i];
49             tem[dep].pos = i;
50             DFS(dep + 1, i + 1);
51         }
52     }
53     return;
54 }
55 
56 int main(void)
57 {
58     #ifdef LOCAL
59         freopen("2610in.txt", "r", stdin);
60     #endif
61 
62     while(scanf("%d%d", &n, &p) == 2)
63     {
64         for(int i = 0; i < n; ++i)
65             scanf("%d", &num[i]);
66         cnt = 0;
67         for(int i = 1; i < n; ++i)
68         {
69             flag = false;
70             len = i;
71             DFS(0, 0);
72             if(cnt >= p || !flag)
73                 break;
74         }
75         printf("\n");
76     }
77     return 0;
78 }
代码君

 

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/3917838.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值