• NYOJ 16 矩形嵌套 【dp DAG】


    题目链接:

      http://acm.nyist.net/JudgeOnline/problem.php?pid=16


    dp:

      设d[i]表示从结点i出发的最长路径长度,状态转移方程为:

      d(i) = max{d(j)+1 | (i,j) ∈ E} 其中,E为边集

    DAG:

      矩形之间的可嵌套关系是一种二元关系,二元关系用图来建模,若X可以嵌套在Y里,则建立一条X指向Y的有向边。

      这个有向图是无环的,因为一个矩形无法直接嵌套在自己内部,即此图是一个DAG。求最大的矩形嵌套数,就是求DAG上的最长路径。


     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 #define clr(c) memset(c, 0, sizeof(c));
     7 
     8 const int MAXL = 1000+10;
     9 typedef struct{
    10     int length;
    11     int width;
    12 }rectangle;
    13 
    14 rectangle R[MAXL]; // 矩形数组
    15 bool G[MAXL][MAXL]; // DAG的邻接矩阵
    16 int d[MAXL]; // 状态转移数组
    17 int Case, n, num1, num2;
    18 
    19 void CreatGraph(){ // 建图
    20     clr(G);
    21     for(int i = 0; i < n; i++){
    22         for(int j = 0; j < n; j++){
    23             if(R[i].length < R[j].length && R[i].width < R[j].width){
    24                 G[i][j] = true; // i 嵌套在 j 中
    25             }
    26         }
    27     }
    28 }
    29 
    30 int dp(int i){
    31     int& ans = d[i]; // 引用
    32     if(ans > 0) return ans;
    33     ans = 1;
    34     for(int j = 0; j < n; j++){
    35         if(G[i][j]) ans = max(ans, dp(j)+1); // dp(j)从j出发的最长路径
    36     }
    37     return ans;
    38 }
    39 
    40 void print_ans(int i){
    41     printf("%d ", i);
    42     for(int j = 0; j < n; j++){
    43         if(G[i][j] && d[i] == d[j]+1){
    44             print_ans(j);
    45             break; // 字典序最小,第一个符合条件的j输出后即退出
    46         }
    47     }
    48 }
    49 
    50 int main(){
    51     scanf("%d", &Case);
    52     while(Case--){
    53         scanf("%d", &n);
    54         for(int i = 0; i < n; i++){ // 强行规定长 > 宽
    55             scanf("%d%d", &num1, &num2);
    56             R[i].length = max(num1, num2);
    57             R[i].width = min(num1, num2);
    58         }
    59         CreatGraph();
    60         clr(d); // 清空状态转移数组
    61         int ans = 0, maxAns = 0;
    62         for(int i = 0; i < n; i++){
    63             int temp = dp(i);
    64             //ans = max(ans, temp); // 输出最大的结果
    65             if(temp > ans){ // 输出最大的结果,并记录最大值的编号(若有相同值取最小编号),用于输出路径
    66                 ans = temp;
    67                 maxAns = i;
    68             }
    69         }
    70         printf("%d
    ", ans);
    71         //print_ans(maxAns); // 输出路径
    72         //printf("
    ");
    73     }
    74 
    75     return 0;
    76 }
  • 相关阅读:
    修改url地址参数
    jquery点击click事件和blur事件冲突如何解决
    js 小数点 取整数
    js正则表达式 验证手机号,email地址和邮政编码
    js轮播功能 标签自动切换 同页面多轮播js
    json 数组操作
    Jquery页面中添加键盘按键事件,如ESC事件
    记录一下。。。服务器 共享文件夹 模拟模拟 IIS 验证的帐户或用户
    vs2015 js 无智能提示解决办法
    解决poshytip 表单高度大于屏幕高端 显示问题
  • 原文地址:https://www.cnblogs.com/miaowTracy/p/4857745.html
Copyright © 2020-2023  润新知