hdu 5128 The E-pang Palace 2014ACM/ICPC亚洲区广州站

这一题开始没看见矩形是平行坐标轴的,如果没有这个要求需要四层循环枚举四个点,判断边是否平行(叉积=0),在判断两个边是否垂直(点积=0)。本题中只要枚举左上角和右下角的顶点,看看能不能找到对应的左下角和右上角的顶点即可。

判断是否相交,就分别判断A的各个顶点是不是在B内部,因为是矩形直接用坐标关系判断即可。如果四个点都在B内部就是包含,这也是合法的情况,返回的是外圈矩形的面积。包含关系需要分别判断A是否包含B和B是否包含A

判断是否相交,就分别判断A的各个顶点是不是在B某一条边上,相交需要判断两次,也要判断B的各个顶点是不是在A某一条边上。比如(0,0),(0,3),(1,0),(1,3)和(0,1),(0,2),(1,1),(1,2)这种相交关系。个人感觉先按照矩形面积从小大大排个序就不要判断两次了,不过想想排序的复杂度也差不多。

所以先将所有的矩形存起来,在分别两两枚举找出最大面积即可。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<ctype.h>
#include<map>
#include<time.h>
#include<bitset>
#include<set>
#include<list>
using namespace std;
//hdu 5128
const int maxn=35;
int N;
int idx;
bool isnode[maxn][maxn];
pair<int,int>node[maxn];
int ans;
class rectangular
{
public:
    pair<int,int>p[4];
public:
    rectangular()
    {
        memset(p,0,sizeof(p));
    }
    int area()
    {
        return (p[2].first-p[0].first)*(p[0].second-p[1].second);
    }
};
rectangular rect[maxn*1000];
bool cmpvertex(pair<int,int>a,pair<int,int>b)
{
    if(a.first==b.first)
    {
        return a.second>b.second;
    }
    else
    {
        return a.first<b.first;
    }
}
//p0----p2
// |         |
//p1----p3
int judge(rectangular a, rectangular b)
{
    int cnt=0;
    int cnt2=0;
    for(int i=0;i<4;i++)
    {
        if(a.p[i].first>b.p[0].first&&a.p[i].first<b.p[2].first&&a.p[i].second<b.p[0].second&&a.p[i].second>b.p[1].second)
        {
            cnt++;
        }
        else if(a.p[i].first==b.p[0].first&&a.p[i].second<=b.p[0].second&&a.p[i].second>=b.p[1].second)//p0-p1
        {
            cnt2++;
        }
        else if(a.p[i].first==b.p[2].first&&a.p[i].second<=b.p[2].second&&a.p[i].second>=b.p[3].second)//p2-p3
        {
            cnt2++;
        }
        else if(a.p[i].second==b.p[0].second&&a.p[i].first>=b.p[0].first&&a.p[i].first<=b.p[2].first)//p0-p2
        {
            cnt2++;
        }
        else if(a.p[i].second==b.p[1].second&&a.p[i].first>=b.p[1].first&&a.p[i].first<=b.p[3].first)//p1-p3
        {
            cnt2++;
        }
    }
    if(cnt2>0)
    {
        return 0;//a and b are touched
    }
    if(cnt==4)
    {
        return 1;//b includes a
    }
    else if(cnt>=1&&cnt<4)
    {
        return 2;//a and b are crossed
    }
    cnt=0;
    cnt2=0;
    for(int i=0;i<4;i++)
    {
        if(b.p[i].first>a.p[0].first&&b.p[i].first<a.p[2].first&&b.p[i].second<a.p[0].second&&b.p[i].second>a.p[1].second)
        {
            cnt++;
        }
         else if(b.p[i].first==a.p[0].first&&b.p[i].second<=a.p[0].second&&b.p[i].second>=a.p[1].second)//p0-p1
        {
            cnt2++;
        }
        else if(b.p[i].first==a.p[2].first&&b.p[i].second<=a.p[2].second&&b.p[i].second>=a.p[3].second)//p2-p3
        {
            cnt2++;
        }
        else if(b.p[i].second==a.p[0].second&&b.p[i].first>=a.p[0].first&&b.p[i].first<=a.p[2].first)//p0-p2
        {
            cnt2++;
        }
        else if(a.p[i].second==b.p[1].second&&a.p[i].first>=b.p[1].first&&a.p[i].first<=b.p[3].first)//p1-p3
        {
            cnt2++;
        }
    }
    if(cnt==4)
    {
        return 3;//a includes b
    }
    if(cnt2>0)
    {
        return 0;//a and b are touched
    }
    return 4;//qualified
}
void solve()
{
    for(int i=0;i<idx;i++)
    {
        for(int j=i+1;j<idx;j++)
        {
//            for(int k=0;k<4;k++)
//            {
//                cout<<rect[i].p[k].first<<" "<<rect[i].p[k].second<<" ";
//            }
//            cout<<endl;
//            for(int k=0;k<4;k++)
//            {
//                cout<<rect[j].p[k].first<<" "<<rect[j].p[k].second<<" ";
//            }
//            cout<<endl;
//            cout<<rect[i].area()<<" "<<rect[j].area()<<endl;
            int ret=judge(rect[i],rect[j]);
            //cout<<ret<<endl;
            if(ret==0||ret==2)
            {
                continue;
            }
            else if(ret==4)
            {
                ans=max(ans,rect[i].area()+rect[j].area());
            }
            else if(ret==1)
            {
                ans=max(ans,rect[j].area());
            }
            else if(ret==3)
            {
                ans=max(ans,rect[i].area());
            }
        }
    }
}
int main()
{
    freopen("input.txt","r",stdin);
    //freopen("out1.txt","w",stdout);
    while(true)
    {
        scanf("%d",&N);
        if(N==0)
        {
            break;
        }
        if(N<8)
        {
            printf("imp\n");
            continue;
        }
        memset(isnode,false,sizeof(isnode));
        memset(node,0,sizeof(node));
        ans=0;
        for(int i=0;i<N;i++)
        {
            int x,y=0;
            scanf("%d %d",&x,&y);
            node[i]=make_pair(x,y);
            isnode[x][y]=true;
        }
        sort(node,node+N,cmpvertex);
        idx=0;
        for(int i=0;i<N;i++)
        {
            int x0=node[i].first;
            int y0=node[i].second;
            for(int j=i+1;j<N;j++)
            {
                int x3=node[j].first;
                int y3=node[j].second;
                if(x3<=x0||y3>=y0)
                {
                    continue;
                }
                if(isnode[x0][y3]==true&&isnode[x3][y0]==true)
                {
                    rect[idx].p[0]=make_pair(x0,y0);
                    rect[idx].p[1]=make_pair(x0,y3);
                    rect[idx].p[2]=make_pair(x3,y0);
                    rect[idx].p[3]=make_pair(x3,y3);
                    //cout<<x0<<" "<<y0<<" "<<x3<<" "<<y3<<" "<<rect[idx].area()<<endl;
                    sort(rect[idx].p,rect[idx].p+4,cmpvertex);
                    idx++;
                }
            }
        }
        solve();
        if(ans>0)
        {
            printf("%d\n",ans);
        }
        else
        {
            printf("imp\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值