hdu1160 dp

hdu1160

题意:给出很多老鼠的数据,分别是它们的体重和跑速,为了证明老鼠越重跑得越慢,要找一组数据,由若干个老鼠组成,保证老鼠的体重依次增加而跑速依次减小,问这组数据最多能有多少老鼠,并按体重从小到大输出这些老鼠的顺序。

并不是难题,我觉得有点类似穷国富国或者是堆砖块,我的做法就是首先将这些老鼠按体重从大到小排序(为什么从大到小呢,因为我是用结构体模拟指针记录了上一只老鼠的序号,所以最终会倒序输出,排序的时候就按倒序排序了)

昂,介绍下我的结构体,是记录了 w(weight),s(speed),n(number),l(last),体重和速度肯定是要记录的用于比较,n 是由于我要进行排序,数组下标会被打乱,所以用 n 单独记录这只老鼠原本的位置,l 则是记录这只老鼠上一只老鼠的数组下标,如果前面没有老鼠,那就是指向第 0 只老鼠(重量是极大,速度是 0,n 、 l 都初始化为0).

当对体重排完序之后,就从前往后开始 dp ,对第 i 只老鼠,遍历从 0 到 i - 1 的老鼠 j ,如果 j 比 i 重而且速度慢,那就 dp[ i ] = max ( dp [ i ] , dp [ j ] + 1 ),并且判断 dp [ i ] 是不是最大值,如果是就记录下 i 便于最后输出数据量最大的一组老鼠。

然后就这么结束了。

恩,接下来是吐槽时间,看见我代码里面一堆堆绿翔色的 debug 代码了吗```是的,一开始我读入都不对,我计数的 c 是在读取数据的时候 ++c 的,但是每次读两个数据,我就很自以为是地一个用了 ++c 一个直接 c,以为会在第一个加了,第二个就是沿用加过的,于是```各种坑,++这种东西还是要足够水平才能用啊,我这种渣渣还是老老实实后面加 c++ 吧```;

这并不是全部,然后我在纠结样例那个顺序究竟是怎么得到的呢!!!为什么我每次都和它有一两个不一样,我试了要不要排速度? dp 值相等的时候要不要取?各种各种,正当我即将绝望想要求助学长的时候```我突然看到说只要求一种可行解就可以了!!!英语啊我的英语啊谁来拯救我的英语啊!!!

恩并不止是这样,当我明白是其中一种正确解就可以的时候我果断提交!WA!!!WTF!!!我换了种姿势又WA了一发,我觉得是时候找学长们谈论一下人生了```然后我突然又发现```由于读入的时候没有说读入多少个只是读到文件结束,所以我自己加了个读 9 个数据就跳出读取循环为了测试给的样例,但是我并记不住把它删掉!```果然把它注释掉就 AC 了,我的心好累,连 hdu 都要欺负我这种智商不过关的渣渣啊```

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define max(a,b) a>b?a:b
 6 #define inf 0x3f3f3f3f
 7 int dp[1050];
 8
 9 struct Mouse{
10     int w,s,n,l;
11 }m[1050];
12
13 int cmp(Mouse m1,Mouse m2){
14     if(m1.w==m2.w)return m1.s<m2.s;
15     return m1.w>m2.w;
16 }
17
18 int main(){
19     int c=1,i,j;
20     while(scanf("%d%d",&m[c].w,&m[c].s)!=EOF){
21         m[c].n=c;
22         m[c].l=0;
23 //        if(c==9)break;
24         c++;
25     }
26 /*
27     printf("\n");
28     for(i=1;i<=c;i++)printf("%d %d\n",m[i].w,m[i].s);
29     printf("\n");
30 */
31     sort(m+1,m+c+1,cmp);
32     m[0].w=inf;
33     m[0].s=0;
34     m[0].l=0;
35     m[0].n=0;
36     int ans=0;
37 /*    printf("\n");
38     for(i=0;i<=c;i++){
39         printf("%d %d\n",m[i].w,m[i].s);
40     }
41     printf("\n");
42 */    for(i=1;i<=c;i++){
43         dp[i]=0;
44         for(j=0;j<i;j++){
45             if(m[j].w>m[i].w&&m[j].s<m[i].s){
46                 if(dp[j]+1>=dp[i]){
47                     dp[i]=dp[j]+1;
48                     m[i].l=j;
49                     if(dp[i]>dp[ans])ans=i;
50                 }
51             }
52         }
53     }
54     printf("%d\n",dp[ans]);
55     while(m[ans].l!=0){
56 //        printf("%d %d ",m[ans].w,m[ans].s);
57         printf("%d\n",m[ans].n);
58         ans=m[ans].l;
59     }
60 //    printf("%d %d ",m[ans].w,m[ans].s);
61     printf("%d\n",m[ans].n);
62     return 0;
63 }

时间: 2024-08-24 03:47:58

hdu1160 dp的相关文章

dp求顺序hdu1160

题意是仅仅求一次的顺序.先依照速度从大到小排序,速度想等到按体重增序排列. 然后基本就变成了求已定顺序序列的最长递增序列递增,跟那个求一致最大序列和的基本一致. dp[i]里存储的是到当前i最大的递增序列个数最大的数. dp[i+1]就是在a[i+1]大于前面的a[j]的情况下,dp[i+1]=dp[j]+1; 输出的就是从最大的dp[]值从后往前输出,所以用了个栈改成从前往后. 以为题意仅仅输出一个正确序列就好. 思路是从開始的结构体排序.打一打就想出来的.bug,调了一天.确定dp[]最大值

DP总结 ——QPH

常见优化 单调队列 形式 dp[i]=min{f(k)} dp[i]=max{f(k)} 要求 f(k)是关于k的函数 k的范围和i有关 转移方法 维护一个单调递增(减)的队列,可以在两头弹出元素,一头压入元素. 队列中维护的是两个值.一个是位置,这和k的范围有关系,另外一个是f(k)的值,这个用来维护单调性,当然如果f(k)的值可以利用dp值在O(1)的时间内计算出来的话队列中可以只维护一个表示位置的变量. 枚举到一个i的时候,首先判断队首元素的位置是否已经不满足k的范围了,如果不满足就将队首

HDU1160:FatMouse&#39;s Speed(最长上升子序列,不错的题)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1160 学的东西还是不深入啊,明明会最长上升子序列,可是还是没有A出这题,反而做的一点思路没有,题意就不多说了,真是怀疑了为什么做这题的时候竟然想用nlog(n)的那个算法, 根本不可能有解啊,真想抽自己一下,最后无奈看了题解,发现他们写的非常棒,记录路径仅用一个数组就可以实现,可惜我没有想到啊,还是做题不深入啊. 首先需要排一下序. 代码如下: #include <iostream> #include

hdu-1160 FatMouse&#39;s Speed 【最长上升子序列】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160 FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9965    Accepted Submission(s): 4427 Special Judge Problem Description FatMo

FatMouse&#39;s Speed(HDU-1160)

一道经典的最长子序列题,不过该题需要维护两个量,体重和速度,所以需要先对一个量进行排序,然后剩下的那个量就可以像处理最长子序列那样做了. 值得一提的是该题需要打印路径,最好的方法是用一个数组pre运用类似链表的结构,来记录路径. 这恰恰就是紫书上数据结构那章例题14中所用的记录最短路路径的方法 . 其中的巧妙和实现细节请读者细细品味. 针对这道题, 由于dp是利用之前计算的结果进行递推得到的,因此,每一步的计算都要用到上一步的结.最长上升子序列,就是枚举当前序列的最后一位,然后从前面递推找最优解

「kuangbin带你飞」专题十二 基础DP

layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 传送门 A.HDU1024 Max Sum Plus Plus 题意 给你N个数,然后你分成M个不重叠部分,并且这M个不重叠部分的和最大. 思路 动态规划最大m字段和,dp数组,dp[i][j]表示以a[j]结尾的,i个字段的最大和 两种情况:1.第a[j

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&