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]); } } }
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]); } } }
仅仅是交换了语句1,2和3的位置,结果确是WA与AC的区别,
原因大概在于必须保证在e以内的任意一条线上都必须要存在on2,on,left值,像那个WA的版本应该是最后的那一根竖线有可能会出现这种情况:只有left值,却没有on值以及on2值