最长单调子序列
2012-10-04 10:48
169 查看
最长单调子序列
1. 问题描述(HDU 1160)
给出一些老鼠的质量和速度, 求一串数据证明老鼠的质量和速度成反比例关系?
2. 算法介绍
首先排序(由小到大), 第一关键字“质量”, 第二关键字“速度“
最长单调子序列方法:
Len(i)表示使证明成立的某串数据最后一只老鼠是第 i 只老鼠的该串长度。
对于第i + 1 只老鼠, Len(i + 1)= max (Len (j) + 1, Len(i + 1)) 且 满足速度和质量成反比例关系。
对于 HDU 1160 , 还需求出具体是哪些老鼠, 用一个数组记录上一个老鼠, 递归输出即可。
3. 简单应用
HDU 1421 搬寝室
HDU 1069 monkey and banana
本题与普通的字符串的最大区别在于字符串中的字符位置是不变的,而方块是可以任意选取的,
因此我们只需要确定每一个方块的位置(方块即字符串中的一个字符)就行了。
本题有多重确定方块位置的方法,可以按面积排序,或者按边长排序都行,其本质都是确保
前面的方块都能放在其后的某个方块的下面,然后按照求最长单调子序列的方法求解即可。
本题的另一个注意点就是,x, y的选取, 一个立方体有三个面可以作为底面,而一个面的长或宽有两种选择
所以本题的底面有6种情况。
HDU 2059 龟兔赛跑
记录从起点开始到其他各点的最短时间。
最短时间是从点i开始,从起点到i的最短时间 + 开车时间 + 加油时间 + 脚踩到点j所花去的时间(如果需要)总和
即为起点到J的最短时间。 (好好理解这个方程, 想想最长单调子序列的方法, 两个循环)
为什么这个方程是对的?
因为,最短时间的来就是选取在哪个站加油,每个站都有可能。而上面的DP,则在每个站点都加一次油,然后一直开,就考虑了
所有的可能加油的站点。
4. 源代码
HDU 1160
HDU 1421
HDU 1069
HDU 2059
1. 问题描述(HDU 1160)
给出一些老鼠的质量和速度, 求一串数据证明老鼠的质量和速度成反比例关系?
2. 算法介绍
首先排序(由小到大), 第一关键字“质量”, 第二关键字“速度“
最长单调子序列方法:
Len(i)表示使证明成立的某串数据最后一只老鼠是第 i 只老鼠的该串长度。
对于第i + 1 只老鼠, Len(i + 1)= max (Len (j) + 1, Len(i + 1)) 且 满足速度和质量成反比例关系。
对于 HDU 1160 , 还需求出具体是哪些老鼠, 用一个数组记录上一个老鼠, 递归输出即可。
3. 简单应用
HDU 1421 搬寝室
按重量排序,相邻的两个物品所产生的疲劳度最小。 dp[i][j] 表示i个物品中取j对物品的最低疲劳度 如果j对物品中包含i物品,dp[i][j] = dp[i - 2][j - 1] + i物品 与 i - 1 物品的差的平方; 如果不包含, dp[i][j] = dp[i - 1][j];
HDU 1069 monkey and banana
本题与普通的字符串的最大区别在于字符串中的字符位置是不变的,而方块是可以任意选取的,
因此我们只需要确定每一个方块的位置(方块即字符串中的一个字符)就行了。
本题有多重确定方块位置的方法,可以按面积排序,或者按边长排序都行,其本质都是确保
前面的方块都能放在其后的某个方块的下面,然后按照求最长单调子序列的方法求解即可。
本题的另一个注意点就是,x, y的选取, 一个立方体有三个面可以作为底面,而一个面的长或宽有两种选择
所以本题的底面有6种情况。
HDU 2059 龟兔赛跑
记录从起点开始到其他各点的最短时间。
最短时间是从点i开始,从起点到i的最短时间 + 开车时间 + 加油时间 + 脚踩到点j所花去的时间(如果需要)总和
即为起点到J的最短时间。 (好好理解这个方程, 想想最长单调子序列的方法, 两个循环)
为什么这个方程是对的?
因为,最短时间的来就是选取在哪个站加油,每个站都有可能。而上面的DP,则在每个站点都加一次油,然后一直开,就考虑了
所有的可能加油的站点。
4. 源代码
HDU 1160
#include <stdio.h> #include <stdlib.h> struct Mouse { int weight; int speed; int index; int pre; }M[1000]; int num[1000]; int cmp (const void *a, const void *b); void print (int max); int main() { int i, j; int n, max; i = 0; while (scanf ("%d%d", &M[i].weight, &M[i].speed) == 2) { M[i].index = i + 1; i ++; } n = i; qsort (M, n, sizeof (struct Mouse), cmp); for (i = 0; i < n; i ++) { num[i] = 1; M[i].pre = i; } for (i = 0; i < n; i ++) { for (j = 0; j < i; j ++) { if (M[i].weight > M[j].weight && M[i].speed < M[j].speed && num[i] < num[j] + 1) { num[i] = num[j] + 1; M[i].pre = j; } } } max = 0; for (i = 0; i < n; i ++) { if (num[i] > num[max]) { max = i; } } printf ("%d\n", num[max]); print (max); return 0; } int cmp (const void *a, const void *b) { struct Mouse *v1 = (struct Mouse *)a; struct Mouse *v2 = (struct Mouse *)b; if (v1->weight != v2->weight) { return v1->weight - v2->weight; } else { return v2->speed -v1->speed; } } void print (int max) { int i = max; if (M[i].pre != i) { print (M[i].pre); printf ("%d\n", M[i].index); } else { printf ("%d\n", M[i].index); } }
HDU 1421
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 100000000 int weight[2001]; int dp[2001][1001]; int cmp (const void *a, const void *b); int main() { int i, j; int n, k; while (scanf ("%d%d",&n, &k) == 2) { for (i = 1; i <= n; i ++) { scanf ("%d", &weight[i]); } qsort (weight + 1, n, sizeof (int), cmp); // 从weight[1]开始排序 for (i = 0; i <= n; i ++) { for (j = 1; j <= k; j ++) { dp[i][j] = MAX; } } for (i = 2; i <= n; i ++) { for (j = 1; j <= k && 2 * j <= i; j ++) { dp[i][j] = dp[i - 2][j - 1] + (weight[i] - weight[i - 1]) * (weight[i] - weight[i - 1]); if (dp[i - 1][j] < dp[i][j]) { dp[i][j] = dp[i - 1][j]; } } } printf ("%d\n", dp [k]); } return 0; } int cmp (const void *a, const void *b) { return *((int *)a) - *((int *)b); }
HDU 1069
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Shape { int x; int y; int z; }s[541]; int cmp (const void *a, const void *b); int height[540]; int main() { int n; int i, j; int x, y, z; int count, max; count = 1; while (scanf ("%d", &n) == 1 && n) { j = 0; for (i = 0; i < n; i ++) { scanf ("%d%d%d", &x, &y, &z); s[j].x = x; s[j].y = y; s[j ++].z = z; s[j].x = y; s[j].y = z; s[j ++].z = x; s[j].x = x; s[j].y = z; s[j ++].z = y; s[j].x = y; s[j].y = x; s[j ++].z = z; s[j].x = z; s[j].y = y; s[j ++].z = x; s[j].x = z; s[j].y = x; s[j ++].z = y; } qsort (s, 6 * n, sizeof (struct Shape), cmp); memset (height, 0, sizeof (height)); max = 0; for (i = 0; i < 6 * n; i ++) { for (j = 0; j < i; j ++) { if (s[j].x > s[i].x && s[j].y > s[i].y) { if (height[i] < height[j]) { height[i] = height[j]; } } } height[i] += s[i].z; if (max < height[i]) { max = height[i]; } } printf ("Case %d:", count ++); printf (" maximum height = %d\n", max); } return 0; } int cmp (const void *a, const void *b) // 边长排序 { struct Shape *v1 = (struct Shape *)a; struct Shape *v2 = (struct Shape *)b; if (v1->x != v2->x) { return v2->x - v1->x; } else if(v1->y != v2->y) { return v2->y - v1->y; } else { return v2->z - v1->z; } } /*int cmp (const void *a, const void *b) // 面积排序 { struct Shape *v1 = (struct Shape *)a; struct Shape *v2 = (struct Shape *)b; int area1, area2; area1 = v1->x * v1->y; area2 = v2->x * v2->y; if (area1 != area2) { return area2 - area1; } else { return v2->z - v1->z; } }*/
HDU 2059
#include <stdio.h> int main() { int len; int i, j; int N, D, T; double t1, t2; int vr, vt1, vt2; int station[102]; double dp[102]; while (scanf ("%d", &len) == 1) { scanf ("%d%d%d", &N, &D, &T); scanf ("%d%d%d", &vr, &vt1, &vt2); for (i = 1; i <= N; i ++) { scanf ("%d", &station[i]); } t1 = (double)len / vr; for (i = 1; i < N + 2; i ++) { dp[i] = 1000000; } dp[0] = 0; station[0] = 0; station[N + 1] = len; // 4000 加入起点和终点 for (i = 1; i < N + 2; i ++) { for (j = 0; j < i; j ++) { if (station[i] - station[j] <= D) { t2 = (station[i] - station[j]) / (double)vt1; } else { t2 = D / (double)vt1 + (station[i] - station[j] - D) / (double)vt2; } if (j != 0) { t2 += T; // 起点油已经加满,其他各点均需要加油,花费时间T } if (dp[i] > t2 + dp[j]) { dp[i] = t2 + dp[j]; } } } if (t1 < dp[N + 1]) { printf ("Good job,rabbit!\n"); } else { printf ("What a pity rabbit!\n"); } } return 0; }
相关文章推荐
- hdu 1950最长单调上升子序列
- 单调最长递增子序列
- 最长单调递增子序列
- LIS 最长单调上升子序列
- POJ1631最长单调递增子序列
- 求解最长单调子序列.
- 时间复杂度为O(nlogn)的最长单调递增子序列
- 最长单调递增子序列
- HDU1069 最长单调子序列变形
- 【训练题】航线设计(优化求较大数据规模的最长单调子序列)
- hdu 4604 Deque (二分法求最长单调子序列)
- 求最长单调递增子序列
- 合唱队形----RQNOJ_26----最长单调子序列
- 最长单调子序列(DP)
- 解题笔记(34)——求最长单调递减子序列
- 拦截导弹----RQNOJ_217----最长单调子序列
- 【bzoj 十连测】[noip2016十连测第九场]Problem B: 小P的单调区间(最长上升子序列+树状数组)
- 单调队列优化的最长上升子序列
- POJ 1065 Wooden Sticks(zoj 1025) 最长单调子序列
- acdream 1426 Beautiful People(双线最长单调子序列)