zoukankan      html  css  js  c++  java
  • NYOJ16 矩形嵌套 【DAG上的DP/LIS】

    矩形嵌套
    时间限制:3000 ms | 内存限制:65535 KB
    难度:4
    描述
    有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。
    输入
    第一行是一个正正数N(0<N<10),表示测试数据组数,
    每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
    随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽
    输出
    每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行
    样例输入
    1
    10
    1 2
    2 4
    5 8
    6 10
    7 9
    3 1
    5 8
    12 10
    9 7
    2 2
    样例输出
    5

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 1005
    struct node
    {
        int x,y;
    }a[N];
    
    bool cmp(node a,node b)
    {
        return (a.x<b.x || a.x==b.x&&a.y<b.y);
    }
    
    int dp[N];
    
    int main()
    {
        int t, n;
        cin >> t;
        while(t--)
        {
            int Max = 0;
            cin >> n;
            for(int i=0; i<n; i++){
                cin >> a[i].x >> a[i].y;
                dp[i] = 1;
                if(a[i].x<a[i].y) swap(a[i].x,a[i].y);//长必须比宽大-鲁棒性
            }
    
            sort(a,a+n,cmp); //按照长、宽由小到大排序
    
            //核心代码:LIS(n^2)
            for(int i=0; i<n; i++){
                for(int j=0; j<i; j++){
                    if(a[j].x < a[i].x && a[j].y < a[i].y) //判断条件:后一个(i)矩阵的长宽都比前一个(j)要大才能容纳前一个形成俄罗斯套娃【突然想到俄罗斯套娃也是这个调调】/嵌套矩阵
                        dp[i] = max(dp[i],dp[j]+1);
                }
            }
    
            //遍寻最大嵌套矩阵
            for(int i=0; i<n; i++)
                Max = max(Max, dp[i]);
            printf("%d
    ",Max);
        }
        return 0;
    }
    /*
    1
    10
    1 2
    2 4
    5 8
    6 10
    7 9
    3 1
    5 8
    12 10
    9 7
    2 2
    */
    
    

    ologn

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 1005
    struct node
    {
        int x,y;
    }a[N];
    
    bool cmp(node a,node b)
    {
        //一般的最末位的元素较小的在之后的会更加有优势 但是嵌套的要大 所以排序时候应该把y由大到小
        return (a.x < b.x || a.x == b.x && a.y > b.y);
    }
    
    int dp[N];
    
    int main()
    {
        int t, n;
        cin >> t;
        while(t--)
        {
            int Max = 0;
            cin >> n;
            for(int i=0; i<n; i++){
                cin >> a[i].x >> a[i].y;
                dp[i] = 1;
                if(a[i].x<a[i].y) swap(a[i].x,a[i].y);
            }
            sort(a,a+n,cmp);
            vector<int> v;
            for(int i=0; i<n; i++){
                if(lower_bound(v.begin(),v.end(),a[i].y) == v.end())
                    v.push_back(a[i].y);
                else  *lower_bound(v.begin(),v.end(),a[i].y) = a[i].y;
            }
            printf("%d
    ",v.size());
        }
        return 0;
    }
    
    

    [图论]

    #include <cstdio>
    #include <cstring>
    
    const int maxn = 1005;
    int n, G[maxn][maxn];
    int a[maxn], b[maxn];
    int dp[maxn];
    
    //将x和y的最大值存在x中
    inline void CMAX(int& x, int y){
        if (y > x){
            x = y;
        }
    }
    
    /* 采用记忆化搜索 求从s能到达的最长路径 */
    int DP(int s){
        int& ans = dp[s];
        if (ans > 0)
            return ans;
        ans = 1;
        for (int j = 1; j <= n; ++j){
            if (G[s][j]){
                CMAX(ans, DP(j) + 1);
            }
        }
        return ans;
    }
    
    void print_ans(int i){
        printf("%d ", i);
        for (int j = 1; j <= n; ++j){
            if (G[i][j] && dp[j] + 1 == dp[i]){
                print_ans(j);
                break;
            }
        }//for(j)
    }
    
    int main()
    {
    #ifdef _LOCAL
        freopen("D:\input.txt", "r", stdin);
    #endif
        while (scanf("%d", &n) == 1){
            //n个矩形
            for (int i = 1; i <= n; ++i){
                //默认a存长,b存宽(a > b)
                scanf("%d%d", a + i, b + i);
                if (a[i] < b[i]){
                    swap(a[i], b[i]);
                }
            }
            /*
                建图 G[i][j]为1表示矩形i可以嵌套在矩形j中
                那么原问题便转化为求DAG上的最长路径
    
                定义状态dp[i]表示从结点i出发可以到达的最长路径
                则 dp[i] = max(dp[j] + 1), 其中 G[i][j]=1,
            */
            memset(G, 0, sizeof G);
            for (int i = 1; i <= n; ++i){
                for (int j = 1; j <= n; ++j){
                    //矩形i的长和宽都小于矩形j的长和宽
                    if (a[i] < a[j] && b[i] < b[j]){
                        G[i][j] = 1; //可以嵌套,则有边
                    }
                }
            }//for(i)
            memset(dp, 0, sizeof dp);
            int ans = 0;
            int best;
            for (int i = 1; i <= n; ++i){
                if (DP(i) > ans){
                    ans = dp[i];
                    best = i;
                }
            }//for(i)
            printf("ans = %d
    ", ans);
            print_ans(best);
            printf("
    ");
        }
        return 0;
    }
    
    
  • 相关阅读:
    HDU 5492 Find a path
    codeforce gym 100548H The Problem to Make You Happy
    Topcoder SRM 144 Lottery
    codeforce 165E Compatible Numbers
    codeforce gym 100307H Hack Protection
    区间DP总结
    UESTC 1321 柱爷的恋爱 (区间DP)
    HDU 4283 You Are the One (区间DP)
    HDU 2476 String painter (区间DP)
    UESTC 426 Food Delivery (区间DP)
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9010404.html
Copyright © 2011-2022 走看看