LA 3695 Distant Galaxy

LA 3695

一张二维图上提供N个点,要求画出一个矩形,这个矩形边上的点要最多

使用暴力法解题,先枚举上下两条边,之后就不能使用两条线进行枚举了,其一是不好统计,其二时间上也耗费大。

可以使用left[i]记录i以前的上下两条边的点数之和,on[i]代表i这条线上的点数,不包括与上下相交的点,on2[i]包括

那么最终答案为on2[i]+left[i]-left[j]+on[j]

那么只需一重循环,在i一定的情况下,保证(i>j)且on[j]-left[j]尽可能的大就好了,其方法如uva11078的开放学分制是一样的

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define M(a) memset(a,0,sizeof(a))
using namespace std;
struct node
{
    int x,y;
    bool operator < (const node & a) const
    {
        return x<a.x;
    }
}eve[111];
int y[111];
int on[111],on2[111],lef[111];

int solo(int n)
{
    int m=unique(y+1,y+1+n)-(y+1);
    if(m<=2) return n;
    sort(y+1,y+1+m);
    sort(eve+1,eve+1+n);
    int ans=0;
    for(int down=1;down<=m;down++)
    {
        for(int up=down+1;up<=m;up++)
        {
            M(lef);M(on);M(on2);
            int e=0;
            int ymax=y[up],ymin=y[down];
            for(int i=1;i<=n;i++)
            {
                if(eve[i].x!=eve[i-1].x||i==1)
                {
                    e++;
                    lef[e]=lef[e-1]+on2[e-1]-on[e-1];
                }
                if(eve[i].y<ymax&&eve[i].y>ymin) on[e]++;
                if(eve[i].y<=ymax&&eve[i].y>=ymin) on2[e]++;
            }
            if(e<=2) return n;
            int cur=0;
            for(int i=1;i<=e;i++)
            {
                ans=max(ans,on2[i]+lef[i]+cur);
                cur=max(cur,on[i]-lef[i]);
            }
        }
    }
    return ans;
}

int main()
{
    int n;
    int ca=1;
    while(cin>>n,n!=0)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>eve[i].x>>eve[i].y;
            y[i]=eve[i].y;
        }
        printf("Case %d: %d\n",ca++,solo(n));
    }
    return 0;
}

 

 

后来又写了一次,发现一些细微的区别会导致完全不同的结果

WA:

 for(int i=1;i<=m;i++)
    {
      for(int j=i+1;j<=m;j++)
      {
         M(left);M(on);M(on2);
          int up=y[j],down=y[i];
          int e=1;
          for(int k=1;k<=n;k++)
          {
              if(p[k].y<up&&p[k].y>down) on[e]++;
              if(p[k].y<=up&&p[k].y>=down) on2[e]++;
              if(p[k].x!=p[k-1].x)
              {
                  e++;
                  left[e]=left[e-1]+on2[e-1]-on[e-1];
              }
          }
          if(e<=2) return n;
          int temp=0;
          for(int h=1;h<=e;h++)
          {
              ans=std::max(ans,on2[h]+left[h]+temp);
              temp=std::max(temp,on[h]-left[h]);
          }
      }
      }
View Code

AC:

 for(int i=1;i<=m;i++)
    {
      for(int j=i+1;j<=m;j++)
      {
         M(left);M(on);M(on2);
          int up=y[j],down=y[i];
          int e=1;
          for(int k=1;k<=n;k++)
          {
              if(p[k].x!=p[k-1].x)
              {
                  e++;
                  left[e]=left[e-1]+on2[e-1]-on[e-1];  //3
              }
              if(p[k].y<up&&p[k].y>down) on[e]++;     //1
              if(p[k].y<=up&&p[k].y>=down) on2[e]++;   //2
          }
          if(e<=2) return n;
          int temp=0;
          for(int h=1;h<=e;h++)
          {
              ans=std::max(ans,on2[h]+left[h]+temp);
              temp=std::max(temp,on[h]-left[h]);
          }
      }
      }
View Code

 

 仅仅是交换了语句1,2和3的位置,结果确是WA与AC的区别,

原因大概在于必须保证在e以内的任意一条线上都必须要存在on2,on,left值,像那个WA的版本应该是最后的那一根竖线有可能会出现这种情况:只有left值,却没有on值以及on2值

posted @ 2015-10-29 13:22  江南何采莲  阅读(171)  评论(0编辑  收藏  举报