Hdu 5064 Find Sequence 解题报告

题目出处:http://acm.hdu.edu.cn/showproblem.php?pid=5064

题意:给定n个数,求满足以下两个条件的子序列的最大长度:

  (1)C1<C2<C3<......<Ct;

  (2)C2-C1<C3-C2<......<Ct-Ct-1.

分析:解结构一定为为N1,N1,N1,......,N1,N2,N3,......,Nt

     设dp[i][j]表示以num[i], num[j]结尾的有效序列的长度,则有
         dp[i][j] = max(dp[k][i]+ 1) ,,,,,,,k<=i且num[i]-num[k]<=num[j]-num[i]
  

    剪枝一:
             考虑非递减序列 num[s],num[k],num[i],num[j] ,num[e],
             容易得到 dp[s][i]<=dp[s][i] (例如1,2,3) 即右端点固定 左端点越远越小,
             同时因为序列从小到大排列,因此 左端点越远num[i]-num[k]越大,
             所以,对于算某一特定的dp[i][j]时num[j]-num[i]是一个定值从k=i开始递减遍历dp[k][i]+ 1 取最大值,待条件不满足时跳出循环。

剪枝二:
             因为 若num[i]-num[k]<=num[j]-num[i]成立 则num[i]-num[k]<=num[j+1]-num[i]必成立,
             即 dp[i][j]<=dp[i][j+1] (例如 1(num[k]),4(num[i]),5(num[j]),8(num[j+1]))
             即 左端点固定 小区间能取到的序列 大区间一定可以取到,
             所以,每次计算新的dp[i][j]时k只要在上次的基础上继续向左遍历dp[k][i]+ 1,取最大值即可。

源代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<map>
 4 using namespace std;
 5 int n,M,num[3000],cnt[3000],size,dp[3000][3000];
 6
 7 int maxVal(int a,int b){return a>b?a:b;}
 8
 9 int main()
10 {
11     int t;
12     scanf("%d",&t);
13     while(t--)
14     {
15         scanf("%d%d",&n,&M);
16         int i,j,k;
17         size = 0;//序列中有size个不同的数
18         map<int,int> mp;
19         map<int,int>::iterator it;
20         //记录序列中某个数i出现了几次,
21         for(i=0;i<n;i++)
22         {
23             int a;
24             scanf("%d",&a);
25             mp[a]++;
26         }
27         //用map是可以默认取数据时从小到大
28         //PS:网络上不用map用数组预先处理的执行时间约600MS,用map约200MS
29         for(it=mp.begin(); it!=mp.end();it++)
30         {
31             num[size] = it->first;
32             cnt[size] = it->second;
33             size++;
34         }
35
36         int res = 1;
37         for(i=0;i<size;i++)
38         {
39             dp[i][i] = cnt[i];
40             res =maxVal(res, dp[i][i]);
41             k=i;
42             int temp = -1;
43             for(j=i+1;j<size;j++)
44             {
45                 for(;k>=0;k--)
46                 {
47                     if(num[i]-num[k]<=num[j]-num[i])
48                     {
49                         temp = maxVal(dp[k][i] + 1,temp);
50                     }
51                     else
52                     {
53                         break;
54                     }
55                 }
56                 dp[i][j] = temp;
57                 res =maxVal(res, dp[i][j]);
58             }
59         }
60         printf("%d\n",res);
61
62     }
63     return 0;
64 }

  

时间: 2024-08-09 06:35:10

Hdu 5064 Find Sequence 解题报告的相关文章

hdu 1711 Number Sequence 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目意思:给出一条有n个数的序列a[1],a[2],......,a[n],和一条有m 个数的序列b[1],b[2],......,b[m],求出b[1],b[2],...,b[m]在序列a中完全匹配时,在序列a中的位置,如果找不到输出-1. 这几天一直在学kmp,该题算是kmp的入门题吧.有个地方要稍稍注意,代码中,主串和模式串的比较初始值为-1,-1,否则如果从0开始,会默认第一个字符是相

hdu 4956 Poor Hanamichi 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956(它放在题库后面的格式有一点点问题啦,所以就把它粘下来,方便读者观看) 题目意思:给出一个范围 [l, r] 你, 问是否能从中找到一个数证明 Hanamichi’s solution 的解法是错的. Hanamichi’s solution 是这样的: 对于某个数 X,从右往左数它的每一位数字(假设第一位是从0开始数).它 偶数位的数字之和 -  奇数位的数字之和  = 3  而且 这个 X

hdu 1514 Free Candies 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1514 题目意思:有4堆糖果,每堆糖果有n个,从上到下排好,取糖果只能从上往下取,取完的糖果放在篮子里,篮子里最多放5个,如果篮子里有两个颜色相同的糖果则可以取走放进口袋里,问最多能取走多少对糖果放进口袋.n<=40, 糖果颜色最多20种. 这题是抄这个人滴:http://fudq.blog.163.com/blog/static/1913502382014239225290/ 有些地方看得不太懂,本

最小生成树,POJ和HDU几道题目的解题报告(基于自己写的模板)

首先POJ题目: 链接:1251 Jungle Roads 题目大意:纯求最小生成树,结果为最小权值边的和.采用邻接表 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 #define maxn 30 //最大顶点个数 8 int n; //顶点数,边数 9 10 struct arcn

hdu 2544 最短路 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目意思:给出 n 个路口和 m 条路,每一条路需要 c 分钟走过.问从路口 1 到路口 n 需要的最短时间是多少. 这题是最短路的入门题,从理解d-i--j---k(wg自创的,呵呵)到默打到修改,搞左两日终于好了,哈哈哈~~~太感动了. 第一次错是 少了Dijkstra()函数中的 for (j = 1; j <= n; j++) . 第二次错是把vis[k=j]=1 写在了 if (!v

hdu acm 2844 Coins 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2844 题目意思:有A1,A2,...,An 这 n 种面值的钱,分别对应的数量是C1,C2,...,Cn.问根据这么多数量的钱 能组成多少个 <= m 的钱. 如果用多重背包来做,超时了...如果用记忆化搜索,还是...超时= =..... 这个方法是网上搜的,觉得好神奇,能看懂一些. 它是根据完全背包的思路做的,但是需要限制每种币种的使用数量,于是就多了个used[] 数组来记录了. ! f[j]

hdu acm 1114 Piggy-Bank 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1114 题目意思:给出一个空的猪仔钱ang 的重量E,和一个装满钱的猪仔钱ang 的重量F你,实质上能装入得钱的重量就是F - E.接着有n 种币种,每个币种有两个属性刻画:面值 + 重量.问恰好装满(注意关键词: 恰好)后,需要的钱的最少数量所对应的钱是多少(有点拗口= =.)拿第一组数据来说, 10 110 2 1 1 30 50 我们当然是用两张30 来填满这个只能装100重量的罐啦,如果都用面

HDU 4303 Hourai Jeweled 解题报告

HDU 4303 Hourai Jeweled 解题报告 评测地址: http://acm.hdu.edu.cn/showproblem.php?pid=4303 评测地址: https://xoj.red/contests/view/1155/1 题目描述 Kaguya Houraisan was once a princess of the Lunarians, a race of people living on the Moon. She was exiled to Earth over

USACO Section2.1 Sorting a Three-Valued Sequence 解题报告

sort3解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你N,而后给出N个数,每个数都是1~3中的一个.请问,要把这个数列升序排好,最少需要进行几次两两交换?[数据范围] 1<=N<