最长单调子序列

来源:互联网 发布:java httpclient 异步 编辑:程序博客网 时间:2024/05/16 06:40

最长单调子序列

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 100000000int 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[n][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;  // 加入起点和终点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;}


 

原创粉丝点击