您的位置:首页 > 其它

nyoj--16 矩形嵌套(经典DP)

2016-02-27 11:37 399 查看
nyoj 16

题意

有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

题解

按白书上的分析,矩形之间的“可嵌套”关系是一个二元关系,可以用图来建模。如果矩形X可以嵌套在矩形Y中,就从X到Y有一条有向边,这就转化为一个DAG,所要求的是DAG上的最长路径。

其次,这个DAG的起点是不固定的,也就是说需要考虑从每个顶点出发所能得到的最长路。现在考虑某一点 i,设 d(i) 表示从结点 i 出发的最长路长度,因为它只能走到它的邻接点,所以状态转移方程为d(i)=max{d(j)+1|(i,j)∈E}

#include <iostream>
#include <fstream>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1000 + 5;
bool  graph[maxn][maxn];
int   a[maxn], b[maxn];
int   n, t;
int   dp[maxn];

void buildGraph()
{
memset(graph, 0, sizeof(graph));
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if((a[i] < a[j] && b[i] < b[j]) || (a[i] < b[j] && b[i] < a[j]))
graph[i][j] = true;
}
}
}

int DP(int i)
{
int& ans = dp[i];
if(ans > 0) return ans;

ans = 1;
for(int j = 0; j < n; ++j)
if(graph[i][j]) ans = max(ans, DP(j) + 1);
return ans;
}

int main()
{
//fstream cin("data.in");
ios::sync_with_stdio(false);
for(cin >> t; t--; )
{
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i] >> b[i];
buildGraph();
memset(dp, 0, sizeof(dp));
int ans = 0;
for(int i = 0; i < n; ++i) ans = max(ans, DP(i));
cout << ans << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nyoj dp middle