zoukankan      html  css  js  c++  java
  • HDU 1160 排序或者通过最短路两种方法解决

    题目大意:

    给定一堆点,具有x,y两个值

    找到一组最多的序列,保证点由前到后,x严格上升,y严格下降,并把最大的数目和这一组根据点的编号输出来

    这里用两种方法来求解:

    1.

    我们可以一开始就将数组根据x由大到小排个序,由前往后取,保证x严格上升了

    只要每次取得过程中找一条x不相等的关于y的最长下降子序列即可,加个回溯,输出所有点

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 const int N = 1005;
     7 int dp[N] , fa[N] , rec[N];
     8 
     9 struct Node{
    10     int x , y , id;
    11     bool operator<(const Node &m)const{
    12         if(x == m.x) return y < m.y;
    13         return x < m.x;
    14     }
    15 }node[N];
    16 
    17 int main()
    18 {
    19     //freopen("a.in" , "r" , stdin);
    20     int k = 0;
    21     while(scanf("%d%d" , &node[k].x , &node[k].y) != EOF){
    22         node[k].id = k + 1;
    23         k++;
    24     }
    25     //先保证都是以x由小到大排列
    26     sort(node , node+k);
    27 
    28     memset(dp , 0 , sizeof(dp));
    29     memset(fa , -1 , sizeof(fa));
    30     dp[0] = 1;
    31     //x已满足上升,现在处理y使其按下降顺序排列即可,按照最长上升子序列的O(n^2)的方法类似处理即可
    32     for(int i = 1 ; i<k ; i++){
    33         dp[i] = 1;
    34         for(int j = 0 ; j<i ; j++){
    35             if(node[j].x != node[i].x && node[i].y < node[j].y){
    36                 if(dp[i] < dp[j] + 1){
    37                     dp[i] = dp[j] + 1;
    38                     fa[i] = j;
    39                 }
    40             }
    41         }
    42     }
    43 
    44     int maxn = 0 , la;
    45     for(int i = 0 ; i<k ; i++){
    46         if(maxn < dp[i]) maxn = dp[i] , la = i;
    47     }
    48 
    49     int cnt = 0;
    50     rec[cnt++] = la;
    51     while(fa[la] >= 0){
    52         rec[cnt++] = fa[la];
    53         la = fa[la];
    54     }
    55     printf("%d
    " , maxn);
    56     for(int i =cnt-1 ;  i>=0 ; i--)
    57         printf("%d
    " , node[rec[i]].id);
    58 
    59     return 0;
    60 }

    2.

    我们对所有m1.x<m2.x , m1.y>m2.y的m1和m2间添加一条有向线段

    这样我们可以从所有入度为0的点出发,进行bfs,每一条边认为长度为1,入度为0的点认为dp[i] = 1表示到达第i个点最多能有多少个物品

    计算最短路径的过程加个回溯这个题目就解决了

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <queue>
      5 #include <iostream>
      6 using namespace std;
      7 const int N = 1005;
      8 int dp[N] , fa[N] , rec[N] , k , t , first[N];
      9 int in[N] , vis[N];
     10 queue<int> q;
     11 
     12 struct Node{
     13     int x , y , id;
     14     bool operator<(const Node &m)const{
     15         if(x == m.x) return y < m.y;
     16         return x < m.x;
     17     }
     18 }node[N];
     19 
     20 struct Edge{
     21     int y , next;
     22 }e[N*N];
     23 
     24 void add_edge(int x, int y)
     25 {
     26     e[k].y = y , e[k].next = first[x];
     27     first[x] = k++;
     28 }
     29 
     30 void bfs(int s)
     31 {
     32     memset(vis , 0 , sizeof(vis));
     33     q.push(s);
     34     vis[s] = 1;
     35     while(!q.empty()){
     36         int u = q.front();
     37         q.pop();
     38         vis[u] = 0;
     39         for(int i = first[u] ; i!=-1 ; i = e[i].next){
     40             int v = e[i].y;
     41             if(dp[v] < dp[u] + 1){
     42                 dp[v] = dp[u] + 1;
     43                 fa[v] = u;
     44                 if(!vis[v]){
     45                     vis[v] = 1;
     46                     q.push(v);
     47                 }
     48             }
     49         }
     50     }
     51 }
     52 
     53 bool ok(int ith1 , int ith2)
     54 {
     55     return node[ith1].x < node[ith2].x && node[ith1].y > node[ith2].y;
     56 }
     57 
     58 int main()
     59 {
     60    // freopen("a.in" , "r" , stdin);
     61     t = 1 , k = 0;
     62     memset(first , -1 , sizeof(first));
     63     memset(dp , 0 , sizeof(dp));
     64     memset(in , 0 , sizeof(in));
     65     while(scanf("%d%d" , &node[t].x , &node[t].y) != EOF){
     66         node[t].id = t + 1;
     67         t++;
     68     }
     69 
     70     for(int i = 1 ; i<t ; i++){
     71         for(int j = 1 ; j<i ; j++){
     72             if(ok(i , j)){
     73                 add_edge(i , j);
     74                 in[j] ++;
     75             }
     76             if(ok(j , i)){
     77                 add_edge(j , i);
     78                 in[i] ++;
     79             }
     80         }
     81     }
     82 
     83     for(int i = 1 ; i<t ; i++)
     84         if(in[i] == 0){
     85             dp[i] = 1;
     86             bfs(i);
     87         }
     88 
     89     int maxn = 0 , la;
     90     for(int i = 1 ; i<t ; i++){
     91         if(maxn < dp[i]){
     92             maxn = max(maxn , dp[i]);
     93             la = i;
     94         }
     95     }
     96 
     97     int cnt = 0;
     98     rec[cnt++] = la;
     99     while(fa[la]){
    100         rec[cnt++] = fa[la];
    101         la = fa[la];
    102     }
    103     printf("%d
    " , maxn);
    104     for(int i = cnt-1 ; i>=0 ; i--)
    105         printf("%d
    " , rec[i]);
    106 
    107     return 0;
    108 }
  • 相关阅读:
    Tensorflow Tutorial 2: image classifier using convolutional neural network Part-1(译)
    TensorFlow Tutorial: Practical TensorFlow lesson for quick learners
    TensorFlow Tutorial: Practical TensorFlow lesson for quick learners
    Builder Pattern(译)
    Mysql锁机制
    Monitorenter
    非静态内部类
    ConcurrentModificationException
    Http2.0协议
    Docker化 springboot项目
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4183434.html
Copyright © 2011-2022 走看看