zoukankan      html  css  js  c++  java
  • 【巧妙预处理系列+离散化处理】【uva1382】Distant Galaxy

    给出平面上的n个点,找一个矩形,使得边界上包含尽量多的点。

    【输入格式】

    输入的第一行为数据组数T。每组数据的第一行为整数n(1≤n≤100);以下n行每行两个整数,即各个点的坐标(坐标均为绝对值不超过109的整数)。输入结束标志为n=0。

    【输出格式】

    对于每组数据,输出边界点个数的最大值。


    先贴题解的精妙预处理:

    不难发现,除非所有输入点都在同一行或者同一列上(此时答案为n),最优矩形的4条边都至少有一个点(一个角上的点同时算在两条边上)。这样,我们可以枚举4条边界所穿过的点,然后统计点数。这样做的时间复杂度为O(n5)(统计点数还需要O(n)时间),无法承受。

    和《子序列》一题类似,可以考虑部分枚举,即只枚举矩形的上下边界,用其他方法确定左右边界,过程如图1-31所示。


    对于竖线i,我们用left[i]表示竖线左边位于上下边界上的点数(注意,不统计位于该竖线上的点),on[i]和on2[i]表示竖线上位于上下边界之间的点数(区别在于on[i]不统计位于上下边界上的点数,而on2[i]要统计)。这样,给定左右边界ij时,矩形边界上的点数为left[j]-left[i]+on[i]+on2[j]。当右边界j确定时,on[i]-left[i]应最大。

    枚举完上下边界后,我们先花O(n)时间按照从左到右的顺序扫描一遍所有点,计算left、on[i]和on2[i]数组,然后枚举右边界j,同时维护on[i]-left[i](i<j)的最大值。这一步本质上等价于例题《开放式学分制》。

     再讲解一下这题的离散化处理


    给每个点一个新的坐标 x坐标 为其原x坐标的排序后位置

         y坐标 为其原y坐标的排序后位置

    对于对距离不敏感的点集问题 这样十分方便处理问题


    贴代码:

    #include <cstdio>  
    #include <cstdlib>  
    #include <cmath>  
    #include <cstring>  
    #include <ctime>  
    #include <algorithm>  
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313   
    const int maxn=100+5;
    using namespace std;
    struct point
    {
    	int x,y;
    };
    point P[maxn];
    int N;
    int YN,XN;
    int ans;
    int FF[maxn][maxn];
    int CE[maxn][maxn];
    int UP[maxn][maxn];
    void input()
    {
    	YN=0;XN=0;
    	memset(FF,0,sizeof(FF));
    	memset(CE,0,sizeof(CE));
    	memset(UP,0,sizeof(UP));
    	for(int i=1;i<=N;i++)
    	scanf("%d%d",&P[i].x,&P[i].y);
    }
    int cmp1(const void *i,const void *j)
    {
    	point *ii=(point *)i,*jj=(point *)j;
    	return ii->x-jj->x;
    }
    void getXN()
    {
    	int i;
    	qsort(P+1,N,sizeof(P[1]),cmp1);
    	for(i=1;i<=N;i++)
    	{
    		if(P[i].x!=P[i-1].x) 
    		{
    			XN++;
    			P[i-1].x=XN-1;
    		}
    		else P[i-1].x=XN;
    	}
    	P[N].x=XN;
    }
    int cmp2(const void *i,const void *j)
    {
    	point *ii=(point *)i,*jj=(point *)j;
    	return ii->y-jj->y;
    }
    void getYN_FF()
    {
    	int i;
    	qsort(P+1,N,sizeof(P[1]),cmp2);
    	for(i=1;i<=N;i++)
    	{
    		if(P[i].y!=P[i-1].y) 
    		{
    			YN++;
    			P[i-1].y=YN-1;
    		}
    		else P[i-1].y=YN;
    		FF[P[i-1].x][P[i-1].y]++;
    	}
    	P[N].y=YN;
    	FF[P[N].x][P[N].y]++;
    }
    void  get_UPCE()
    {
    	for(int i=1;i<=XN;i++)
    	 for(int j=1;j<=YN;j++)
    	 {
    	 	CE[i][j]=CE[i][j-1]+FF[i][j];
    	 	UP[i][j]=UP[i-1][j]+FF[i][j];
    	 }	
    }
    int On[maxn],Left[maxn],On2[maxn];
    void get_On_Left_On2(int a,int b)
    {
    	memset(On,0,sizeof(On));
    	memset(Left,0,sizeof(Left));
    	memset(On2,0,sizeof(On2));
    	for(int i=1;i<=YN;i++)
    	{
    		On[i]=UP[b-1][i]-UP[a][i];
    		On2[i]=UP[b][i]-UP[a-1][i];
    		Left[i]=CE[a][i-1]+CE[b][i-1];
    	}
    }
    void solve()
    {
    	ans=0;
    	int tempans=0,tempi=0;
    	for(int i=1;i<=XN;i++)
    	 for(int i2=i+1;i2<=XN;i2++)
    	  {
    	  		get_On_Left_On2(i,i2);
    	  		tempans=0;
    			  for(int j=1;j<=YN;j++)
    			  {
    				  	if(ans<Left[j]+On2[j]+tempans)
    	        			 ans=Left[j]+On2[j]+tempans;
    				  	if(tempans<On[j]-Left[j]) 
    				  		tempans=On[j]-Left[j];
    			  }
    	  } 
    }
    int main()
    {
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	int Case=0;
    	while(cin>>N&&N)
    	{
    		Case++;
    		input();
    		if(N<=3) {
    				 		printf("Case %d: %d
    ",Case,N);
    				 		continue;
    				 }
    		getXN();
    		getYN_FF();
    		get_UPCE();
    		solve();
    		printf("Case %d: %d
    ",Case,ans);
    	}
    }
      



  • 相关阅读:
    2020软件工程个人作业06————软件工程实践总结作业
    2020软件工程作业01
    班级博客V2.1版本更新日志
    博客园班级手机版
    班级帮助文档
    问题累计
    2020 软件工程作业06
    2020 软件工程作业04
    2020 软件工程作业03
    2020软件工程02
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480442.html
Copyright © 2011-2022 走看看