HDOJ 5128 The E-pang Palace

本文介绍了一种通过暴力枚举方法构造矩形并对这些矩形进行嵌套判断的算法实现。该方法首先通过点坐标确定矩形,然后判断两个矩形间是否存在完全嵌套关系,以找到满足特定条件的最大面积组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题虽然是暴力,但是我确实学到了。。。。每句对角线的高端做法。

参考博客:

https://blog.youkuaiyun.com/ck_boss/article/details/41720811

我自己的代码:

解释代码中的一点,就是Judge里面的之所以要两次相互判断,是因为如果只判断一次inside是无法判断A包含B和B包含A的其中一种情况的,也就是说只能包含其中一种情况,会漏掉一种情况。

//C - The E-pang Palace
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
#define MAXN 50
#define MAXN2 1010
#define INF 0x7f7f7f7f

struct Point
{
    int x,y;
}p[MAXN];

struct Matrix
{
    Point P[4];
    int Area;
};

vector<Matrix> M;
int Map[MAXN2][MAXN2];

bool Online(int i,int j)//判断是否是对角线
{
    if(p[i].x==p[j].x||p[i].y==p[j].y)
        return true;
    return false;
}

void Make_Retan(int i,int j)//构造矩形
{
    Matrix m;
    int x1,y1;//对角线对应的剩下的两个点
    int x2,y2;

    x1=max(p[i].x,p[j].x);
    y1=min(p[i].y,p[j].y);
    x2=min(p[i].x,p[j].x);
    y2=max(p[i].y,p[j].y);
    if(Map[x1][y1]&&Map[x2][y2]&&Map[x1][y2]&&Map[x2][y1])//剩余的两个点在图上存在
    {
        m.P[0].x=x2;
        m.P[0].y=y1;
        m.P[1].x=x1;
        m.P[1].y=y1;
        m.P[2].x=x1;
        m.P[2].y=y2;
        m.P[3].x=x2;
        m.P[3].y=y2;
        m.Area=(x1-x2)*(y2-y1);
        M.push_back(m);
    }
}

bool Inside(int &k,Point pp,Matrix X)
{
    int l=X.P[0].x;
    int r=X.P[2].x;
    int up=X.P[2].y;
    int down=X.P[0].y;
    if((pp.x>l)&&(pp.x<r)&&(pp.y>down)&&(pp.y<up))//完全嵌套在里面,没有点或边相交
        k=1;
    if((pp.x>=l)&&(pp.x<=r)&&(pp.y>=down)&&(pp.y<=up))
        return true;
    return false;
}

int Judge(int i,int j)
{
    int k1,k2,k3,k4;
    int res1,res2,res3,res4;
    Matrix A=M[i],B=M[j];

    k1=k2=k3=k4=0;
    res1=Inside(k1,A.P[0],B);
    res2=Inside(k2,A.P[1],B);
    res3=Inside(k3,A.P[2],B);
    res4=Inside(k4,A.P[3],B);
    if(res1||res2||res3||res4)
    {
        if(k1&&k2&&k3&&k4)
            return B.Area;
        return -INF;
    }
    k1=k2=k3=k4=0;
    res1=Inside(k1,B.P[0],A);
    res2=Inside(k2,B.P[1],A);
    res3=Inside(k3,B.P[2],A);
    res4=Inside(k4,B.P[3],A);
    if(res1||res2||res3||res4)
    {
        if(k1&&k2&&k3&&k4)
            return A.Area;
        return -INF;
    }
    //return A.Area+B.Area;
    //if(res1==false&&res2==false&&res3==false&&res4==false)
    return A.Area+B.Area;
	//return -INF;
}

int main()
{
    int i,j;
    int N;
    int ans;

    while(scanf("%d",&N)&&N)
    {
        memset(p,0,sizeof(p));
        memset(Map,0,sizeof(Map));
        for(i=0;i<N;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            Map[p[i].x][p[i].y]=1;
        }
        M.clear();
        for(i=0;i<N;i++)//枚举对角线构造矩形
        {
            for(j=i+1;j<N;j++)
            {
                if(Online(i,j))//判断是否是对角线
                    continue;
                Make_Retan(i,j);//构造矩形(但是不一定会成功,因为这条对角线对应的另外两个点不一定存在)
            }
        }
        ans=-INF;
        for(i=0;i<M.size();i++)//枚举任意两个已经构造的矩形来求满足条件的最大和
        {
            for(j=i+1;j<M.size();j++)
            {
                ans=max(ans,Judge(i,j));//判断两个矩形是否满足条件,如果满足则算出面积和
            }
        }
        if(ans==-INF)
            printf("%s\n","imp");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值