HDU-5128-阿房宫

原题
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
题意:
有n个点从中挑选出两个不同的四个点组成两个边与坐标轴平行的矩形,要求两个矩形不能够相交或者接触,求出满足条件的最大的两个矩形面积之和。(题目未明确说出)若是在两个矩形形成回字形则取大外圈矩形面积。
题解:
由于数据较小可以暴力枚举,先从中找到所有满足条件的矩形,再在矩形中找到符合条件的求最大面积,注意这道题目有一个坑就是形成回字行也是符合题意的。
附上AC代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int n,cnt,t[1000][2],ans;//t数组用来储存矩形
int mp[250][250];
struct node
{
    int x,y;
}st[35];
struct rectangle
{
    node p1,p2;
    int area;
}r[2000];
bool cmp(node a,node b)
{
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.y;
}
int check(int i,int j)//检查i矩形和j矩形是否满足条件,若是不满足则返回 -1,若是满足则返回1,回字形返回2
{

    if ( r[i].p2.x < r[j].p1.x ) return 1;
    if ( r[i].p2.y < r[j].p1.y ) return 1;
    if ( r[i].p1.x > r[j].p2.x ) return 1;
    if ( r[i].p1.y > r[j].p2.y ) return 1;
    if ( r[i].p1.x < r[j].p1.x && r[i].p1.y < r[j].p1.y
        &&r[i].p2.x > r[j].p2.x && r[i].p2.y > r[j].p2.y ) return 2;
    else return 0;
}
int main()
{
    while(cin>>n,n)
    {
        memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
        {
            cin>>st[i].x>>st[i].y;
            mp[st[i].x][st[i].y] = 1;//若是存在(i,j)记录为一
        }
        if(n<8){cout<<"imp"<<endl;continue;}//如果小于八个点则一定不可能构成两个不接触的矩形
        sort(st+1,st+n+1,cmp);//对于st排序,这样保证排在后边的点都比前面的点大(x2>x1,或者x1==x2且y2>y1)
        cnt=1,ans=-1;//初始化
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)//找出所有的矩形
        {
            if(st[j].x>st[i].x&&st[j].y>st[i].y)//寻找矩形对角线元素,对角线元素不能是竖直的或者水平的。
            if(mp[st[i].x][st[j].y]&&mp[st[j].x][st[i].y])//如果矩形里四个点都存在则可以构成一个矩形
            {

                    r[cnt].p1.x = st[i].x , r[cnt].p1.y = st[i].y,//计入矩形
                    r[cnt].p2.x = st[j].x , r[cnt].p2.y = st[j].y,
                    r[cnt++].area = ( st[j].x - st[i].x ) * ( st[j].y - st[i].y );//计算矩形面积
            }
        }
        cnt--;
        for(int i=1;i<cnt;i++)
            for(int j=i+1;j<=cnt;j++)//遍历所有矩形
        {
            if ( check(i,j)  == 1 )
                ans = max ( ans , r[i].area + r[j].area );
            else if ( check(i,j) == 2 )//回字形,取较大的
                ans = max ( ans , r[i].area );
        }
        if(ans==-1)
            cout<<"imp"<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

之前写的一种方法,比较麻烦,也WA了。但本人找不出错误(只缘身在此山中吧),希望有空闲的人可以帮我找出错误评论留言!(万分感谢)
附上WA代码:

/*
大家主要看看思路,具体代码,不要复制粘贴此WA代码。
*/
#include <iostream>
#include <cmath>
using namespace std;
int n,cnt,t[1000][2],ans;//t数组用来储存矩形
struct node
{
    int x,y;
}st[35];
bool fin(int x,int y)//能否在所有点中找到(x,y)这一点
{
    for(int i=1;i<=n;i++)
    {
        if(st[i].x==x&&st[i].y==y)
            return true;
    }
    return false;
}
int check(int i,int j)//检查i矩形和j矩形是否满足条件,若是不满足则返回 -1,若是满足则返回当前下的面积之和
{
    int a=t[i][0];//矩形i
    int b=t[i][1];
    int c=t[j][0];//矩形j
    int d=t[j][1];
    int left=st[a].x,right=st[b].x,up=st[b].y,down=st[a].y;
    int left2=st[c].x,right2=st[d].x,up2=st[d].y,down2=st[c].y;
    int ext;
    if(left>right){ext=left,left=right,right=ext;}//调整left,right,up,down使之符合逻辑
    if(up<down){ext=up,up=down,down=ext;}
    if(left2>right2){ext=left2,left2=right2,right2=ext;}
    if(up2<down2){ext=up2,up2=down2,down2=ext;}
    int s1=(up-down)*(right-left),s2=(up2-down2)*(right2-left2);
    if(down<down2&&up>up2&&left<left2&&right>right2)//特殊情况:回字形
    {
        return s1;
    }
    else if(down>down2&&up<up2&&left>left2&&right<right2)//特殊情况:回字形
    {
        return  s2;
    }
    else if(down2>up||up2<down||left2>right||right2<left)//满足条件,如果第二个矩形的下界大于第一个上界则一定满足,其他一样
    {
        return s1+s2;
    }
    else return -1;//正常情况,直接输出两个面积之和
}
int main()
{
    while(cin>>n,n)
    {
        for(int i=1;i<=n;i++)
            cin>>st[i].x>>st[i].y;
        if(n<8){cout<<"imp"<<endl;continue;}//如果小于八个点则一定不可能构成两个不接触的矩形
        cnt=1,ans=-1;//初始化
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)//找出所有的矩形
        {
            if(st[i].x==st[j].x||st[i].y==st[j].y)continue;//寻找矩形对角线元素
            if(fin(st[i].x,st[j].y)&&fin(st[j].x,st[i].y))//如果矩形里四个点都存在则可以构成一个矩形
            {
                int x=st[i].x;//矩形中第三个点的x和y
                int y=st[j].y;
                int flag=0;
                for(int k=1;k<cnt;k++)
                {
                    int e=t[k][0],f=t[k][1];//列举每一个已经在t中的点
                    if(st[e].x==x&&st[e].y==y)//若是此矩形已经列入t数组则不再重复计入
                        {flag=1;break;}
                    if(st[f].x==x&&st[f].y==y)
                       {flag=1;break;}
                }
                if(flag==1)continue;
                t[cnt][0]=i;//计入矩形的两个不相邻的顶点
                t[cnt][1]=j;
                cnt++;
            }
        }
        cnt--;
        for(int i=1;i<cnt;i++)
            for(int j=i+1;j<=cnt;j++)//遍历所有矩形
        {
            int res=check(i,j);
            ans=ans>res?ans:res;
        }
        if(ans!=-1)
            cout<<ans<<endl;
        else
            cout<<"imp"<<endl;
    }
    return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/82989971