矩形嵌套

时间限制: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

对于这道题目,我们可以有两种写法。
第一种写法:(DP+快速排序)
因为题目要我们选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内,而矩形又有长和宽两个因素。我们就可以开一个结构体来存储每一个
矩形的长和宽,读入时判断一下长和宽的大小,保证长小于宽,以便我们后边进行快速排序。接着快速排序一遍,写一个比较函数把每一个矩形的长按照从大到小排序。接下来我们
就可以直接DP了。
注意:MAX的初值应设为1,因为当没有矩形可以互相嵌套时,就不会触发if (NODE[k].A<NODE[j].A&&NODE[k].B<NODE[j].B),自然也不会更新到MAX值。而当没有矩形可以互相
嵌套时,符合条件的矩形数为1,所以MAX初值应该设置为1,这样才可以保证输出的答案是有效的。
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int read()
{
int f=,x=; char c=getchar();
while (c>''||c<'') {if (c=='-') f=-; c=getchar();}
while (c>='' && c<='') {x=x*+c-''; c=getchar();}
return x*f;
}
struct node
{
int A;
int B;
}NODE[];
bool comp(const node&a,const node&b)
{
if (a.A==b.A) return a.B<b.B;
return a.A<b.A;
}
int T,N,F[],MAX;
int main()
{
T=read();
for (int i=; i<=T; i++) {
MAX=;
N=read();
for (int j=; j<=N; j++) F[j]=;
for (int j=; j<=N; j++) {
NODE[j].A=read();
NODE[j].B=read();
if (NODE[j].A>NODE[j].B) {
int t=NODE[j].A;
NODE[j].A=NODE[j].B;
NODE[j].B=t;
}
}
sort(NODE+,NODE+N+,comp);
for (int j=; j<=N; j++)
for (int k=; k<j; k++)
if (NODE[k].A<NODE[j].A&&NODE[k].B<NODE[j].B) {
if (F[k]+>F[j]) F[j]=F[k]+;
if (F[j]>MAX) MAX=F[j];
}
printf("%d\n",MAX);
}
return ;
}

矩形嵌套

第二种写法:(DP+DAG模型+记忆化搜索)

Tips:DAG:有向无环图。由于一个矩形无法直接或间接地嵌套到自己的内部,所以这个有向图是无环的。

这种写法是紫书上推荐的,所以网络上的代码大多是这种写法。我们还是开一个结构体来存储每一个矩形的长和宽,然后就两重循环枚举每两个矩形之间是否可以嵌套,如果可以嵌套,

就将G[i][j]标记为1,意味着i到j有边相连。然后DFS记忆化搜索每一个矩形(实际上就是每一个点,因为我们已经把矩形间的嵌套关系建模成DAG了,自然每一个矩形都变成了DAG中的

每一个点。),我这里用的DFS是有返回值的,而不是一个纯过程,DFS(NUM)返回的是从NUM点出发的最长路径,也就是最多可以嵌套的矩形个数。然后找出最长路径,记录下来,就

是答案了。

我这里还是想讲一讲这个记忆化搜索的函数,打一下批注以助于理解。

int DFS(int NUM)//寻找NUM点出发的最长路径
{
  int SP=1;//注意:SP要定义在函数里,这样子两层递归之间的SP才不会互相伤害。 SP用于记录当层NUM点出发的最长路径长度。
  if (BOOK[NUM]>0) return BOOK[NUM];//BOOK[NUM]存储着NUM点出发的最长路径。如果BOOK[NUM]>0,这就意味着NUM点出发的最长路径已经被确定了,也就没有必要继续搜索

NUM点出发的最长路径了,就直接返回NUM点出发的最长路径,作为上一层需要的答案组成之一。
  for (int i=1; i<=N; i++)
  if (G[NUM][i]) SP=la(SP,DFS(i)+1);//如果NUM点和i点之间是连通的,SP=max(SP,DFS(i)+1),这一点运用的思想与DP一样,不作解释。
  BOOK[NUM]=SP;//搜索完当层NUM点出发的最长路径,就标记下去。
  return SP;
}

记忆化搜索的核心就是标记和搜索,标记已经搜索过的部分和内容,下一次再到这里时就不需要再耗时搜索一遍,因为结果已经确定了,所以直接返回结果就可以。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int read()
{
int f=,x=; char c=getchar();
while (c>''||c<'') {if (c=='-') f=-; c=getchar();}
while (c>='' && c<='') {x=x*+c-''; c=getchar();}
return x*f;
}
struct node
{
int A;
int B;
}NODE[];
int T,N,MAX=,F[],SP;
bool G[][];
int BOOK[];
int la(int A,int B)
{
if (A>B) return A;
return B;
}
int DFS(int NUM)
{
int SP=;
if (BOOK[NUM]>) return BOOK[NUM];
for (int i=; i<=N; i++)
if (G[NUM][i]) SP=la(SP,DFS(i)+);
BOOK[NUM]=SP;
return SP;
}
int main()
{
T=read();
while (T--) {
MAX=;
memset(BOOK,,sizeof(BOOK));
memset(G,,sizeof(G));
N=read();
for (int i=; i<=N; i++) {
NODE[i].A=read(); NODE[i].B=read();
}
for (int i=; i<=N; i++)
for (int j=; j<=N; j++)
if ((NODE[i].A<NODE[j].A&&NODE[i].B<NODE[j].B)||
(NODE[i].A<NODE[j].B&&NODE[i].B<NODE[j].A)) G[i][j]=;
for (int i=; i<=N; i++)
if (DFS(i)>MAX) MAX=DFS(i);
printf("%d\n",MAX);
}
return ;
}

嵌套矩形

有问题可以直接在评论里面提问,有需要转载的请得到我的允许,否则按侵权处理。

NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索的更多相关文章

  1. poj1191 棋盘分割【区间DP】【记忆化搜索】

    棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description ...

  2. ACM学习历程—ZOJ3471 Most Powerful(dp && 状态压缩 && 记忆化搜索 && 位运算)

    Description Recently, researchers on Mars have discovered N powerful atoms. All of them are differen ...

  3. 【区间dp】【记忆化搜索】UVALive - 3516 - Exploring Pyramids

    f(i,j)=sum(f(i+1,k-1)*f(k,j) | i+2<=k<=j,Si=Sk=Sj). f(i+1,k-1)是划分出第一颗子树,f(k,j)是划分出剩下的子树. #incl ...

  4. 【56测试】【字符串】【dp】【记忆化搜索】【数论】

    第一题:神秘大门 大意: 两个字符串A,B,按字典序最大的顺序输出B 的每个字符在A 中的位置,如果B不全在A中,输出No,否则Yes. 解: 这道题就是一遍的扫描,因为要按字典序最大的输出,所以从后 ...

  5. UVA1351-----String Compression-----区间DP(记忆化搜索实现)

    本文出自:http://blog.csdn.net/dr5459 题目地址: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&a ...

  6. 专题1:记忆化搜索/DAG问题/基础动态规划

      A OpenJ_Bailian 1088 滑雪     B OpenJ_Bailian 1579 Function Run Fun     C HDU 1078 FatMouse and Chee ...

  7. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  8. HDU 1208 Pascal's Travels 经典 跳格子的方案数 (dp或者记忆化搜索)

    Pascal's Travels Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Su ...

  9. kuangbin专题十二 HDU1078 FatMouse and Cheese )(dp + dfs 记忆化搜索)

    FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

随机推荐

  1. Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate

    (1)将Maven项目先clean,接着install下 (2)运行mvn mybatis-generator:generate命令 注意修改generatorConfig.xml的location: ...

  2. MySQL binlog_format (Mixed,Statement,Row)[转]

    MySQL 5.5 中对于二进制日志 (binlog) 有 3 种不同的格式可选:Mixed,Statement,Row,默认格式是 Statement.总结一下这三种格式日志的优缺点. MySQL ...

  3. 在 OC 中调用 Swift 代码

    1.在 Objective-C 项目中使用 Swift 代码 1)在 OC 项目中创建 .Swift 文件,文件中的格式为其本有的格式. 2)Xcode 提示是否创建 Objective-C brid ...

  4. python3版本中的zip函数

    例如,有两个列表: 1 2 >>>a = [1,2,3] >>>b = [4,5,6] 使用zip()函数来可以把列表合并,并创建一个元组对的列表. 1 2 > ...

  5. 安装astrixx firefox插件

    以上步骤适用于firefox 45.0.1. 将astrixx的firefox插件下载到本地,这个插件的下载地址很难找...全名是astrixx proxy switcher about:config ...

  6. apache kylin2.10在原生hadoop集群上安装

    Install Kylin Download latest Kylin binaries at http://kylin.apache.org/download Export KYLIN_HOME p ...

  7. Linux嵌入式时区修改

  8. android开发(46) 使用 textview实现文字的阴影效果,浮雕效果

    前言 最近看到一些文字的阴影效果很有意思,尝试了下,形成本文.“平面效果“是我们平时常见的平面的样子.“阴影效果”会给人一种凸起的感觉.浮雕效果会给一种雕刻“凹陷”的感觉. 演示效果图 方法 使用 t ...

  9. hdoj:2042

    #include <iostream> using namespace std; int main() { int n,a; while (cin >> n) { while ...

  10. Java知多少(96)绘图之设置字型和颜色

    Java绘图中,显示文字的方法主要有三种:(1)drawString(String str,int x,int y):在指定的位置显示字符串.(2)drawChars(char data[],int ...