题目的意思是给定k个盒子,每个盒子的维度有n dimension

问最多有多少个盒子能够依次嵌套

但是这个嵌套的规则有点特殊,两个盒子,D = (d1,d2,...dn) ,E = (e1,e2...en) 只要盒子D的任意全排列,小于盒子E,那么就说明

盒子D能放入盒子E中,其实就是将两个盒子的维度排序,如果前一个盒子的维度依次小于后一个盒子,那么就说明前一个盒子能放入后一个盒子中

这个题目能够转化为最长递增子序列。

首先将盒子的维度从小到大排序,然后将k个盒子,按照排序后的第一维度从小到大排序

这样中的目的是,后面的盒子一定放不到前面的盒子里面,这样是为了消除无后效性。

如果不排序,那么将有后效性,比如第一个盒子不选,但是第二个盒子可以放到第一个盒子里面。

然后就转化为最长递增序列的问题了。

  1. /*
  2. 感觉像是变形的最长递增子序列
  3. 如何快捷的判断一个盒子进过变换能放到另一个盒子里面呢?
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <algorithm>
  8. using namespace std;
  9. const int INF = <<;
  10. struct node
  11. {
  12. int minNum;
  13. int id;
  14. int dimension[];
  15. bool operator<(const node&rhs)const
  16. {
  17. return minNum < rhs.minNum;
  18. }
  19. }a[];
  20. bool canInput[][];//canInput[i][j]判断j能不能放到i里面去
  21. int dp[];
  22. int path[];
  23. int ans[];
  24. int main()
  25. {
  26.  
  27. int n,k,i,j,z;
  28. while(scanf("%d%d",&k,&n)!=EOF)
  29. {
  30. memset(ans,,sizeof(ans));
  31. memset(canInput,false,sizeof(canInput));
  32. memset(dp,,sizeof(dp));
  33. for(i=; i<k; ++i)
  34. {
  35. dp[i] = ;
  36. path[i] = i;
  37. a[i].minNum = INF;
  38. a[i].id = i+;
  39. for(j=; j<n; ++j)
  40. {
  41. scanf("%d",&a[i].dimension[j]);
  42. a[i].minNum = min(a[i].minNum,a[i].dimension[j]);
  43. }
  44. sort(a[i].dimension,a[i].dimension+n);
  45. }
  46.  
  47. sort(a,a+k);
  48. for(i=; i<k; ++i)//预处理,判断i能不能放到j里面去
  49. for(j=i+; j<k; ++j)
  50. {
  51. bool can = true;
  52. for(z=; z<n; ++z)
  53. {
  54. if(a[i].dimension[z] >= a[j].dimension[z])
  55. can = false;
  56. }
  57. if(can)
  58. canInput[j][i] = true;
  59. }
  60. //这里就是求最长递增子序列,时间复杂度是O(k*k)
  61. for(i=; i<k; ++i)
  62. for(j=; j<i; ++j)
  63. {
  64. if(canInput[i][j])//预处理之后,就变成了一维的最长递增子序列的求解了
  65. {
  66. if(dp[j]+ >dp[i])
  67. {
  68. dp[i] = dp[j]+;
  69. path[i] = j;
  70. //break; 这里可不能break, 比如例子:1 2 3 4 5 11 12 13 10 14
  71. }
  72. }
  73. }
  74. int cnt = ,index;
  75. for(i=; i<k; ++i)
  76. if(cnt < dp[i])
  77. {
  78. cnt = dp[i];
  79. index = i;
  80. }
  81.  
  82. printf("%d\n",cnt);
  83. ans[--cnt] = a[index].id;
  84.  
  85. while(path[index]!=index)
  86. {
  87. ans[--cnt] = a[path[index]].id;
  88. index = path[index];
  89. }
  90. printf("%d",ans[cnt++]);
  91. while(ans[cnt]!=)
  92. {
  93. printf(" %d",ans[cnt++]);
  94. }
  95. puts("");
  96. }
  97. return ;
  98. }

当然也可以建图(dag图),然后求最长路, 最长路的一种求法就是进行拓扑排序,然后进行最长递增子序列dp,  拓扑排序同上面的排序一样,也是为了消除后效性

然后这种做法,相当于上面,太复杂了。 但是是为了天马行空的想法而A题,而不是为了A题而A题。

  1. /*
  2. 建图(dag图),
  3. 拓扑排序
  4. dp
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <algorithm>
  10. #include <stack>
  11. using namespace std;
  12. const int INF = <<;
  13. struct node
  14. {
  15. int dimension[];
  16.  
  17. }a[];
  18. bool canInput[][];//canInput[i][j]判断i能不能放到j里面去
  19. int dp[];
  20. int path[];
  21. int ans[];
  22. int in[];
  23. int sequeue[];
  24. int main()
  25. {
  26. int n,k,i,j,z;
  27. while(scanf("%d%d",&k,&n)!=EOF)
  28. {
  29. memset(ans,,sizeof(ans));
  30. memset(canInput,false,sizeof(canInput));
  31. memset(dp,,sizeof(dp));
  32. memset(in,,sizeof(in));
  33. for(i=; i<k; ++i)
  34. {
  35. dp[i] = ;
  36. path[i] = i;
  37. for(j=; j<n; ++j)
  38. {
  39. scanf("%d",&a[i].dimension[j]);
  40. }
  41. sort(a[i].dimension,a[i].dimension+n);
  42. }
  43.  
  44. for(i=; i<k; ++i)//预处理,建图
  45. for(j=i+; j<k; ++j)
  46. {
  47. bool can = true;
  48. for(z=; z<n; ++z)
  49. {
  50. if(a[i].dimension[z] >= a[j].dimension[z])
  51. can = false;
  52. }
  53. if(can)
  54. canInput[i][j] = true;
  55. can = true;
  56. for(z=; z<n; ++z)
  57. {
  58. if(a[i].dimension[z] <= a[j].dimension[z])
  59. can = false;
  60. }
  61. if(can)
  62. canInput[j][i] = true;
  63.  
  64. }
  65. //每个结点的入度
  66. for(i=; i<k; ++i)
  67. {
  68. for(j=; j<k; ++j)
  69. if(canInput[i][j])
  70. in[j]++;
  71. }
  72. //拓扑排序,sequeue数组存在排序之后的序列
  73. for(i=; i<k; ++i)
  74. {
  75. for(j=; in[j]&&j<k; ++j)
  76. NULL;
  77. in[j] = -;
  78. sequeue[i] = j;
  79. for(z=; z<k; ++z)
  80. if(canInput[j][z])
  81. in[z]--;
  82. }
  83.  
  84. //对拓扑排序之后的序列进行最长递增子序列的dp
  85. for(i=; i<k; ++i)
  86. for(j=; j<i; ++j)
  87. {
  88. if(canInput[sequeue[j]][sequeue[i]] && dp[j]+>dp[i])//sequeue[i]
  89. {
  90. dp[i] = dp[j]+;
  91. path[i] = j;
  92. }
  93. }
  94. int cnt = ,index;
  95. for(i=; i<k; ++i)
  96. if(cnt < dp[i])
  97. {
  98. cnt = dp[i];
  99. index = i;
  100. }
  101. printf("%d\n",cnt);
  102.  
  103. ans[--cnt] = index;
  104. while(path[index] != index)
  105. {
  106. ans[--cnt] = path[index];
  107. index = path[index];
  108. }
  109. //sequeue[i]
  110. printf("%d",sequeue[ans[cnt++]]+);
  111. while(ans[cnt]!=)
  112. {
  113. printf(" %d",sequeue[ans[cnt++]]+);
  114. }
  115. puts("");
  116. }
  117. return ;
  118. }

uva103(最长递增序列,dag上的最长路)的更多相关文章

  1. [LeetCode] Number of Longest Increasing Subsequence 最长递增序列的个数

    Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: I ...

  2. [LeetCode] 673. Number of Longest Increasing Subsequence 最长递增序列的个数

    Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: I ...

  3. POJ 2533 Longest Ordered Subsequence 最长递增序列

      Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequenc ...

  4. NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)

    本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽. 本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这 ...

  5. UVa 10285 最长的滑雪路径(DAG上的最长路)

    https://vjudge.net/problem/UVA-10285 题意: 在一个R*C的整数矩阵上找一条高度严格递减的最长路.起点任意,但每次只能沿着上下左右4个方向之一走一格,并且不能走出矩 ...

  6. Leetcode 674.最长递增序列

    最长递增序列 给定一个未经排序的整数数组,找到最长且连续的的递增序列. 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3. 尽管 [1,3 ...

  7. XHXJ's LIS HDU - 4352 最长递增序列&数位dp

    代码+题解: 1 //题意: 2 //输出在区间[li,ri]中有多少个数是满足这个要求的:这个数的最长递增序列长度等于k 3 //注意是最长序列,可不是子串.子序列是不用紧挨着的 4 // 5 // ...

  8. LIS(最长的序列)和LCS(最长公共子)总结

    LIS(最长递增子序列)和LCS(最长公共子序列)的总结 最长公共子序列(LCS):O(n^2) 两个for循环让两个字符串按位的匹配:i in range(1, len1) j in range(1 ...

  9. Vulnerable Kerbals CodeForces - 772C【拓展欧几里得建图+DAG上求最长路】

    根据拓展欧几里得对于同余方程 $ax+by=c$ ,有解的条件是 $(a,b)|c$. 那么对于构造的序列的数,前一个数 $a$  和后一个数 $b$ ,应该满足 $a*x=b(mod m)$ 即 $ ...

随机推荐

  1. 外国的Delphi网站

    www.phidels.com delphifr.com http://www.swissdelphicenter.com/torry/showcode.php?id=787 B4A delphifa ...

  2. POJ1422 最小路径覆盖入门

    题意:DAG求最小路径覆盖. 注意:二分匹配只试用于求DAG的最小路径覆盖, 有环就不行,具体可以理解证明. 对n个点进行拆点,分成左右两排点,对于边<u, v> 建  <u', v ...

  3. uva 10196 Check The Check

    题目:10196 - Check The Check 思路:水题..模拟 这个代码,前半部分是在数统机房上课的时候写的,挫了点,懒得改了. #include <cstdio> #inclu ...

  4. Swift - 日期选择控件(UIDatePicker)的用法

    1,使用storyboard创建日期选择控件 首先我们将一个UIDatePicker控件和一个按钮直接添加到Main.Storyboard上.该按钮是为了点击时弹出提示框显示当前选择的日期和时间. 同 ...

  5. POJ 1742 hdu 2844 Coins

    题目链接:http://poj.org/problem?id=1742 http://acm.hdu.edu.cn/showproblem.php?pid=2844 题目分类:动态规划 代码: #in ...

  6. 怎样在Android本地视频播放器开发

    在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...

  7. GMM高斯混合模型学习笔记(EM算法求解)

    提出混合模型主要是为了能更好地近似一些较复杂的样本分布,通过不断添加component个数,能够随意地逼近不论什么连续的概率分布.所以我们觉得不论什么样本分布都能够用混合模型来建模.由于高斯函数具有一 ...

  8. Rapha&#235;l 中文帮助文档(API)

    http://html5css3webapp.com/raphaelApi.htm

  9. 【Struts2学习笔记(11)】对action的输入校验和XML配置方式实现对action的全部方法进行输入校验

    在struts2中,我们能够实现对action的全部方法进行校验或者对action的指定方法进行校验. 对于输入校验struts2提供了两种实现方法: 1. 採用手工编写代码实现. 2. 基于XML配 ...

  10. setChecked方法触发onCheckedChanged监听器问题

    有时须要在程序初始化界面时,讲有些比如toggleButton等控件依照需求勾选,此时会发现,当我setChecked时会触发onCheckedChanged监听器,导致这部分代码被调用两次.解决方法 ...