[关闭]
@Acqua 2019-01-17T13:23:11.000000Z 字数 932 阅读 883

HDU1160 FatMouse's Speed(Jan. 17th, 2019) LIS路径输出

动态规划

题目来源

题意

给定一个二元集合,求其中元素所构成的使递增且递减的最长序列。

思路

最长上升子序列的路径记录。
1. 链表(实现简单)
2. 倒推

反思

  1. 尽量用最正规风格书写代码(原因见代码注释)。
  2. LIS路径输出只需要在更新时加一个后缀指针,然后搜索式迭代输出。

代码

  1. // La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N = 1e3 + 5;
  8. struct node{
  9. int m, v, id;
  10. } p[N];
  11. bool pluie(node x, node y){
  12. return x. m == y. m ? x. v < y. v : x. m > y. m;
  13. }
  14. int f[N], adv[N];
  15. int main(){
  16. // freopen("testdata.txt", "r", stdin);
  17. printf("%d", adv[1000]);
  18. int n = 1;
  19. while(scanf("%d%d", &p[n]. m, &p[n]. v)!=EOF){
  20. p[n]. id = n; // 此处不可简写为 p[n]. id = n++,因为赋值语句从右至左执行,会出错
  21. n++;
  22. }
  23. n--; sort(p + 1, p + n + 1, pluie);
  24. p[0] = (node){1e9, 0, 0};
  25. int root = 0;
  26. for(int i = 1; i <= n; i++){
  27. f[i] = 0;
  28. for(int j = 0; j < i; j++){
  29. if(p[i]. m < p[j]. m && p[i]. v > p[j]. v){
  30. if(f[i] <= f[j] + 1){
  31. f[i] = f[j] + 1;
  32. adv[i] = j;
  33. if(f[root] < f[i]) root = i;
  34. }
  35. }
  36. }
  37. }
  38. printf("%d\n", f[root]);
  39. while(adv[root]){
  40. printf("%d\n", p[root]. id);
  41. root = adv[root];
  42. }
  43. printf("%d", p[root]. id);
  44. return 0;
  45. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注