HDU--3457--Rectangles--记忆化搜索

14 篇文章 0 订阅

Rectangles

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 707    Accepted Submission(s): 284
Problem Description
A rectangle in the Cartesian plane is speci ed by a pair of coordinates (x1 , y1) and (x2 , y2) indicating its lower-left and upper-right corners, respectively (where x1 ≤ x2 and y1 ≤ y2). Given a pair of rectangles,A = ((x A 1 , y A 1 ), (x A 2 ,y A 2 )) and B = ((x B 1 , y B 1 ), (x B 2 , y B 2 )), we write A ≤ B (i.e., A "precedes" B), if x A 2 < x B 1 and y A 2 < y B 1 :In this problem, you are given a collection of rectangles located in the two-dimension Euclidean plane. Find the length L of the longest sequence of rectangles (A 1,A 2,…,A L) from this collection such that A 1 ≤ A 2 ≤ … ≤ A L.
 
Input
The input fi le will contain multiple test cases. Each test case will begin with a line containing a single integer n (where 1 ≤ n ≤ 1000), indicating the number of input rectangles. The next n lines each contain four integers x i 1 ,y i 1 ,x i 2 ,y i 2 (where -1000000 ≤ x i 1 ≤ x i 2 ≤ 1000000, -1000000 ≤ y i 1 ≤ y i 2 ≤ 1000000, and 1 ≤ i ≤ n), indicating the lower left and upper right corners of a rectangle. The end-of-file is denoted by asingle line containing the integer 0.
 
Output
For each input test case, print a single integer indicating the length of the longest chain.
 
Sample Input
   
   
3 1 5 2 8 3 -1 5 4 10 10 20 20 2 2 1 4 5 6 5 8 10 0
 

Sample Output
   
   
2 1
 


题意:给你N个矩形的左下角跟右上角坐标,然后找出这样一组序列使得其中的每一项与它的后一项满足一个条件,条件是前一项的右上角顶点的X,Y坐标都比后一项的左下角顶点的小,这样的序列可能有多个,求出最长那个的长度(最后一项没有后一项,你懂的,他就是最大的那个)

解析:用记忆化搜索来减少重复搜索的时间,做了很多记忆化搜索题目的人基本很快KO这个题


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Max(a,b) a>b?a:b
using namespace std;
int n;
int dp[1111],map[1111][1111];
struct node
{
    int x1,x2,y1,y2;
}s[1111];
int dfs(int x)
{
    int i,j,k,l;
    if(dp[x])return dp[x];	//先前有数据了就不用再搜了
    for(i=0;i<n;i++)
    if(map[x][i])
    {
        dp[x]=Max(dp[x],dfs(i)+1);	//dp[x]要记录的是最大的那个值,值:由这个点往后最长的序列长度
    }
    dp[x]=Max(dp[x],1);	//当然如果是最大的那个就要赋值1
    return dp[x];
}
int main (void)
{
    int i,j,k,l,x1,x2,y1,y2,sum;
    while(scanf("%d",&n)!=EOF&&n)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            s[i].x1=x1;
            s[i].x2=x2;
            s[i].y1=y1;
            s[i].y2=y2;
        }
        memset(map,0,sizeof(map));
        memset(dp,0,sizeof(dp));
        for(i=0;i<n;i++)	//建立关联方便搜索
        for(j=0;j<n;j++)
        {
            if(s[i].x2<s[j].x1&&s[i].y2<s[j].y1)
            {
                map[i][j]=1;
            }
        }
        sum=0;
        for(i=0;i<n;i++)	//可能最长的那个序列的第一个矩形不是输入序列中的第一个
        {
            sum=Max(sum,dfs(i));
        }
        printf("%d\n",sum);
    }
    return 0;
}

总结:记录最优状态,以后搜索到这里的时候就可以直接调用这个状态



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值