第三场-D-Partition

题目链接:点击打开链接

(一)题面:

Description

The Ents are known as the shepherds of the forest. Treebeard, the oldest living Ent in Middle Earth, needs to determine which trees he is to shepherd and which trees are to be shepherded by his young fellow Ent, Bregalad. They have a rectangular portion of Fangorn forest containing an even number of trees that they need to divide into two pieces using a single straight boundary line. In order to equitably distribute the workload, Treebeard and Bregalad have decided that each of their halves of the forest need to contain equal area and contain an equal number of trees. If a tree lies exactly on the dividing line, then that tree is counted in one or the other of the halves of the forest but not both. Any tree exactly on the dividing line may be assigned to either Treebeard or Bregalad.

Input


Output

For each test case, print out N/2 lines. On each line, print two space-separated integers xixi and yiyi, denoting the coordinates of the ithithtree in the half of the forest that is to be shepherded by Treebeard.

Sample Input

2 5 6
2 3
3 3
4 5 6
1 5
2 5
3 5
4 5
4 10 11
5 1
5 2
5 3
5 4
0 0 0

Sample Output

3 3
1 5
2 5
5 1
5 2

(二)题目大意:

给定一个长宽分别为H、W的长方形,给出长方形中的n个点的坐标,让你画一条直线将长方形划分为面积相等的两个区域,且两个部分中的点的数目相等,线上面的点可以划分到任意一个区域。


(三)解题思路:

  1. 无论怎么划分,直线必过矩形的中心位置,因为题面中提到,W和H不会同时为偶数,故中心位置上不会有点存在。所以我们只需要找一条过矩形中心点的直线,使直线的两边的点的数目相等。
  2. 我们首先把矩形分为上下两个部分,并给定矩形下部分(A,包括一半的横轴,图中红线)的点的权值为-1,上部分(B)的点权值为1。为后续处理方便,我们把所有B部分的点中心旋转到矩形上部分,如图。

  3. 先统计矩形下部分的点的数目,然后从过中心点的水平线逆时针扫描,遇到权值为1的点的时候(说明该点需要加入到A部分),则A部分的点的数目+1,否则说明需要将这个点从A部分踢出(手动模拟一下,其实就是下部分的点出了A部分),数目-1。
  4. 因为需要逆时针扫描所有点,我们需要先把所有的点以中心点为基准点进行极角排序(不懂度娘),使所有点逆时针排列。
  5. 扫描直到A部分的点的数目为N/2。
  6. 然后输出扫过的点中值为1的点,未扫过的点中权值为-1的点,注意输出权值为-1的点的时候把坐标还原。

(四)具体代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<map>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=5e4+10;
int N,W,H;
struct node{
    int x,y,flag;
    bool operator < (const node &n1){
        if((x-W/2.0)*(n1.y-H/2.0)-(y-H/2.0)*(n1.x-W/2.0))
            return (x-W/2.0)*(n1.y-H/2.0)-(y-H/2.0)*(n1.x-W/2.0)>0;
        return x<n1.x;
    }
}Node[maxn];
int main(){
    freopen("in.txt","r",stdin);
    while(~scanf("%d%d%d",&N,&W,&H)&&(N||W||H)){
        int num=0,p;
        for(int i=1;i<=N;i++){
            scanf("%d%d",&Node[i].x,&Node[i].y);
            Node[i].flag=1;
            if(Node[i].y*2<H||(Node[i].y*2==H&&Node[i].x*2<W)){
                Node[i].flag=-1;num++;
                Node[i].x=W-Node[i].x;
                Node[i].y=H-Node[i].y;
            }
        }
        sort(Node+1,Node+N+1);
        for(p=1;p<=N;p++){
            num+=Node[p].flag;
            if(num*2==N)break;
        }
        for(int i=1;i<=N;i++){
            if(i<=p&&Node[i].flag==1)
                printf("%d %d\n",Node[i].x,Node[i].y);
            if(i>p&&Node[i].flag==-1)
                printf("%d %d\n",W-Node[i].x,H-Node[i].y);
        }
    }
    return 0;
}

(五)总结:
  1. 这个题当时也没怎么看,补题的时候才想到去年学长们好像讲过这个方法,但是当时没有补题,所以并不是很清楚。这里补一遍也是get新技能了。

猜你喜欢

转载自blog.csdn.net/xbb224007/article/details/80017029
今日推荐