矩阵覆盖(DAG上的dp 或者 LIS)

思路完全模仿lrj白书。

25题斩。

具体而言,我们发现两个矩形之间是包含关系,比如说A包含于B,我们可以认为,A可以推出B,同理若B可以推出C,则A也可以推出C。

这就好像是一个DAG,于是本题转化成了求DAG上的最长路问题。

我们只需要对于每一个点都dp一下就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1005;

int t, n;

struct node
{
    int x, y;
}a[maxn];

int g[maxn][maxn], vis[maxn], d[maxn];

int dp(int x)
{
    int& ans = d[x];//经典套路,最后ans的值将自动代入d[x]
    if (vis[x]) return d[x];//记忆化搜索,表示已经搜过了。
    vis[x] = 1;
    ans = 1;
    for (int i = 1; i <= n; i++)
        if (g[x][i])
            ans = max(ans, dp(i) + 1);
    return ans;
}

void print_ans(int x)
{
    printf("%d ", x);
    for (int j = 1; j <= n; j++)
        if(g[x][j] && d[x] == d[j] + 1)
        {
            print_ans(j);
            break;//字典序最小。
        }
}

void solve()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d%d", &a[i].x, &a[i].y);
        if (a[i].x > a[i].y) swap(a[i].x, a[i].y);
    }
    memset(g, 0, sizeof g);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if(a[i].x < a[j].x && a[i].y < a[j].y)
            {
                g[i][j] =  1;
            }
    int mx = 0;
    memset(d, 0, sizeof d);
    memset(vis, 0, sizeof vis);
    int jl;
    for (int i = 1; i <= n; i++)
        if (!vis[i])
        {
            int t = dp(i);
            if (t > mx)
            {
                mx = t;
                jl = i;
            }
        }
            
    printf("%d\n", mx);
    print_ans(jl);
}

int main()
{
    scanf("%d", &t);
    while (t--) solve();
    return 0;
} 

 

posted @ 2017-10-23 15:15  yohanlong  阅读(450)  评论(0编辑  收藏  举报