HDU - 5128 The E-pang Palace(计算几何+暴力)

这是一个关于计算几何的问题,来源于HDU的5128题。题目要求在E-pang Palace的遗址上,利用剩余的立柱构建两个不相交的矩形围栏,最大化总面积。输入包含多个测试用例,每个用例给出立柱的坐标,输出应为可能的最大总面积,若无法构建则输出'imp'。解决方案是通过暴力枚举矩形的对角线,判断并排除不合格的情况。

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

The E-pang Palace

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 4351    Accepted Submission(s): 2345


Problem Description

E-pang Palace was built in Qin dynasty by Emperor Qin Shihuang in Xianyang, Shanxi Province. It was the largest palace ever built by human. It was so large and so magnificent that after many years of construction, it still was not completed. Building the great wall, E-pang Palace and Qin Shihuang's tomb cost so much labor and human lives that people rose to fight against Qin Shihuang's regime. 

Xiang Yu and Liu Bang were two rebel leaders at that time. Liu Bang captured Xianyang -- the capital of Qin. Xiang Yu was very angry about this, and he commanded his army to march to Xianyang. Xiang Yu was the bravest and the strongest warrior at that time, and his army was much more than Liu Bang's. So Liu Bang was frighten and retreated from Xianyang, leaving all treasures in the grand E-pang Palace untouched. When Xiang Yu took Xianyang, he burned E-pang Palce. The fire lasted for more than three months, renouncing the end of Qin dynasty.

Several years later, Liu Bang defeated Xiangyu and became the first emperor of Han dynasty. He went back to E-pang Palace but saw only some pillars left. Zhang Liang and Xiao He were Liu Bang's two most important ministers, so Liu Bang wanted to give them some awards. Liu Bang told them: "You guys can make two rectangular fences in E-pang Palace, then the land inside the fences will belongs to you. But the corners of the rectangles must be the pillars left on the ground, and two fences can't cross or touch each other." 

To simplify the problem, E-pang Palace can be consider as a plane, and pillars can be considered as points on the plane. The fences you make are rectangles, and you MUST make two rectangles. Please note that the rectangles you make must be parallel to the coordinate axes.

The figures below shows 3 situations which are not qualified(Thick dots stands for pillars):


Zhang Liang and Xiao He wanted the total area of their land in E-pang Palace to be maximum. Please bring your computer and go back to Han dynasty to help them so that you may change the history.

 Input

There are no more than 15 test case.

For each test case:

The first line is an integer N, meaning that there are N pillars left in E-pang Palace(4 <=N <= 30).

Then N lines follow. Each line contains two integers x and y (0 <= x,y <= 200), indicating a pillar's coordinate. No two pillars has the same coordinate.

The input ends by N = 0.

 Output

For each test case, print the maximum total area of land Zhang Liang and Xiao He could get. If it was impossible for them to build two qualified fences, print "imp".

 Sample Input

8 0 0 1 0 0 1 1 1 0 2 1 2 0 3 1 3 8 0 0 2 0 0 2 2 2 1 2 3 2 1 3 3 3 0

 Sample Output

2 imp

 Source

2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大)

题意:n个点,找出两个矩形,矩形的边必须都平行于坐标轴,并且这两个矩形不能出现题目中图示的那三种情况,求出这两个矩形的面积和的最大值,不存在输出imp

思路:n最多为30,暴力就行了,枚举对角线,先把所有能行成的符合条件的矩形求出来,然后两个两个的枚举矩形,判断两个矩形的之间的位置关系,根据点与矩形的关系来判断矩形与矩形的关系,注意回字形也符合题意

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 36;
struct Point
{
    int x,y;
    Point(){}
    Point(int _x,int _y)
    {
        x = _x;
        y = _y;
    }
    bool operator<(const struct Point& a) const
    {
        if(x == a.x) return y < a.y;
        else return x < a.x;
    }
}p[MAXN];
struct Rec
{
    Point a,b,c,d;
    Rec(){}
    Rec(Point _a,Point _b,Point _c,Point _d)
    {
        a = _a;
        b = _b;
        c = _c;
        d = _d;
    }
};
set<Point> st;
vector<Rec> R;
int judge(Point p,Rec r)
{
    int minx,maxx,miny,maxy;
    minx = min(min(r.a.x, r.b.x),min(r.c.x, r.d.x));
    miny = min(min(r.a.y, r.b.y),min(r.c.y, r.d.y));
    maxx = max(max(r.a.x, r.b.x),max(r.c.x, r.d.x));
    maxy = max(max(r.a.y, r.b.y),max(r.c.y, r.d.y));
    if(p.x > minx && p.x < maxx && p.y > miny && p.y < maxy) return 1;

    if(   (p.x == minx && p.y <= maxy && p.y >= miny)
       || (p.x == maxx && p.y <= maxy && p.y >= miny)
       || (p.y == miny && p.x <= maxx && p.x >= minx)
       || (p.y == maxy && p.x <= maxx && p.x >= minx)) return 0;

    return 3;
}
int solve(int i,int j)
{
    //printf("\n %d %d %d %d %d %d %d %d ",R[i].a.x,R[i].a.y,R[i].b.x,R[i].b.y,R[i].c.x,R[i].c.y,R[i].d.x,R[i].d.y);
    //printf("\n %d %d %d %d %d %d %d %d ",R[j].a.x,R[j].a.y,R[j].b.x,R[j].b.y,R[j].c.x,R[j].c.y,R[j].d.x,R[j].d.y);
    //printf("\n");
    int iminx,imaxx,iminy,imaxy;
    int jminx,jmaxx,jminy,jmaxy;
    iminx = min(min(R[i].a.x, R[i].b.x),min(R[i].c.x, R[i].d.x));
    iminy = min(min(R[i].a.y, R[i].b.y),min(R[i].c.y, R[i].d.y));
    imaxx = max(max(R[i].a.x, R[i].b.x),max(R[i].c.x, R[i].d.x));
    imaxy = max(max(R[i].a.y, R[i].b.y),max(R[i].c.y, R[i].d.y));
    jminx = min(min(R[j].a.x, R[j].b.x),min(R[j].c.x, R[j].d.x));
    jminy = min(min(R[j].a.y, R[j].b.y),min(R[j].c.y, R[j].d.y));
    jmaxx = max(max(R[j].a.x, R[j].b.x),max(R[j].c.x, R[j].d.x));
    jmaxy = max(max(R[j].a.y, R[j].b.y),max(R[j].c.y, R[j].d.y));
    int resi,resj;
   // printf("%d %d %d %d\n",iminx,imaxx,iminy,imaxy);
    resi = (imaxy - iminy) * (imaxx - iminx);
    resj = (jmaxy - jminy) * (jmaxx - jminx);
    int a,b,c,d;
    int aa,bb,cc,dd;
    a = judge(R[i].a,R[j]);
    b = judge(R[i].b,R[j]);
    c = judge(R[i].c,R[j]);
    d = judge(R[i].d,R[j]);
    aa = judge(R[j].a,R[i]);
    bb = judge(R[j].b,R[i]);
    cc = judge(R[j].c,R[i]);
    dd = judge(R[j].d,R[i]);
    //printf("%d %d\n",resi,resj);
    if(a == 1 && b == 1 && c == 1 && d == 1) return resj;
    if(aa == 1 && bb == 1 && cc == 1 && dd == 1) return resi;
    if(a == 1 || b == 1 || c == 1 || d == 1) return 0;
    if(aa == 1 || bb == 1 || cc == 1 || dd == 1) return 0;
    if(a == 0 || b == 0 || c == 0 || d == 0) return 0;
    if(aa == 0 || bb == 0 || cc == 0 || dd == 0) return 0;
    return resi + resj;
}
int main(void)
{
    int n,i,j,k,f,sz;
    int ans;
    while(scanf("%d",&n) != EOF && n) {
        st.clear();
        R.clear();
        for(i = 1; i <= n; i++) {
            scanf("%d %d",&p[i].x,&p[i].y);
            st.insert(p[i]);
        }
        for(i = 1; i <= n; i++) {
            for(j = 1; j <= n; j++) {
                if(j == i) continue;
                if(p[i].x == p[j].x || p[i].y == p[j].y) continue;
                if( st.count(Point(p[j].x,p[i].y)) && st.count(Point(p[i].x,p[j].y)) ) {
                    //printf("\n %d %d \n %d %d\n %d %d \n %d %d\n\n ",p[i].x,p[j].y,p[i].x,p[i].y,p[j].x,p[i].y,p[j].x,p[j].y);
                    R.push_back( Rec(p[i],p[j],Point(p[j].x,p[i].y),Point(p[i].x,p[j].y)) );
                }
            }
        }
        sz = R.size();
        ans = 0;
        for(i = 0; i < sz; i++) {
            for(j = i + 1; j < sz; j++) {
                ans = max(ans,solve(i,j));
            }
        }
        if(ans == 0) printf("imp\n");
        else printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值