HDU5128 The E-pang Palace(2014年广州赛区)

题目:     题目链接


The E-pang Palace

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


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
 

题意:给你n个点,取这n个顶点的某些顶点作为矩形的顶点,问你存不存在两个矩形的面积之和最大。限制条件:这两个举行不能有接触和重叠,但是可以包含在内。

不存在输出"imp"

题解:由于n只有4到30这么大,所以直接暴力求解就可以了。

一、首先我们要判断存不存在矩形,如何判断?

       这里有个小技巧,通过确定两个点的对角线来判断能不能构成矩形。

如图:


        我们先判断A,B这两点所连的直线是不是水平或者竖直,如果是就跳过。如果是则判断C,D这两个点是不是都存在。如果存在则能构成矩形,如果不能,就不能构成。

然后我们在确定第二个矩形。

二、第二个矩形的确定。

       第二个矩形(假设是EFGH)的确定首先要排除点A,B,C,D这四个点,并且EFGH这四个点不能有任何一个在ABCD内(包括边与定点)。(如题图)

       但是这里有一种特殊情况。如图:



    我们确定了ABCD,但是EFGH包含了ABCD,所以我们要反过来判断ABCD是不是在EFGH内。如果在就取EFGH的面积,如果不在就取ABCD+AEFHG的面积。完毕。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
#define LL __int64
const int  MOD = 1e9 + 7;
const int N = 2e2 + 15;
const int INF = (1 << 30) - 1;
const int letter = 130;
using namespace std;
int n;
int x[N], y[N];
int vis[N][N];
int dis[N][N];
int check(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy) {
    ///边界的处理
    int maxx = max(ax, bx);
    int minx = min(ax, bx);
    int maxy = max(ay, by);
    int miny = min(ay, by);
    ///处理好的四个点
    int dir[4][2] = {{cx, cy}, {cx, dy}, {dx, cy}, {dx, dy}};
    int sum = 0;
    int fg = 0;
    for(int i = 0; i < 4; i++) {
        int xx = dir[i][0];
        int yy = dir[i][1];
        if(minx <= xx && xx <= maxx && miny <= yy && yy <= maxy) { ///在第一个矩形内
            sum++;
            ///挨着的
            if((xx == minx && miny <= yy && yy <= maxy) || (xx == maxx && miny <= yy && yy <= maxy) || (yy == miny && minx <= xx && xx <= maxx) || (yy == maxy && minx <= xx && xx <= maxx)) {
                fg = 1;
                break;
            }
        }
    }
    if(fg == 1) return -1;
    if(sum == 4) {
        return (maxx - minx) * (maxy - miny);
    } ///在矩形里面
    else if(sum == 1 || sum == 2 || sum == 3) return -1; ///相交于矩形
    else {
        ///第一个是小的 ,第二个把第一个包含在内
        int vir[4][2] = {{minx, miny}, {minx, maxy}, {maxx, miny}, {maxx, maxy}};
        int flag = 0;
        int fg = 0;
        ///以第二个矩形为边界
        int maxxx = max(cx, dx);
        int minxx = min(cx, dx);
        int maxyy = max(cy, dy);
        int minyy = min(cy, dy);
        for(int i = 0; i < 4; i++) {
            int xx = vir[i][0];
            int yy = vir[i][1];
            if(minxx <= xx && xx <= maxxx && minyy <= yy && yy <= maxyy) { ///在第二个矩形内
                flag++;
                if((xx == minxx && minyy <= yy && yy <= maxyy) || (xx == maxxx && minyy <= yy && yy <= maxyy) ||(yy == minyy && minxx <= xx && xx <= maxxx)||( yy == maxyy && minxx <= xx && xx <= maxxx)) {
                    fg = 1;
                    break;
                }
            }
        }
        if(fg == 1) return -1;
        if(flag != 4) return (maxx - minx) * (maxy - miny) + abs((cx - dx) * (cy - dy));
        else  return abs((cx - dx) * (cy - dy));
    }
}
int main() {
    while(scanf("%d", &n) && n) {
        int max1 = -1;
        memset(vis, 0, sizeof(vis));///地图中存在的点
        memset(dis, 0, sizeof(dis));
        for(int i = 0; i < n; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            x[i] = a, y[i] = b;
            vis[a][b] = 1;
        }
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++) {
                if(x[i] != x[j] && y[i] != y[j]) { ///不在同一条直线上
                    if(vis[x[i]][y[j]] && vis[x[j]][y[i]]) { ///从对角线上找起
                        for(int k = 0; k < n; k++)
                            for(int v = k + 1; v < n; v++) {
                                ///判断这四个点是否符合条件
                                if(x[k] != x[v] && y[k] != y[v]) {
                                    ///找到第二个三角形
                                    if(vis[x[k]][y[v]] && vis[x[v]][y[k]]) {
                                        ///判断第二个三角形和第一个三角形的关系
                                        max1 = max(max1, check(x[i], y[i], x[j], y[j], x[k], y[k], x[v], y[v]));
                                    }
                                }
                            }
                    }
                }
            }
        if(max1 == -1) printf("imp\n");
        else printf("%d\n", max1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值