Distant Galaxy UVALive - 3695 遥远的银河系 矩阵边界枚举

题目链接 

You are observing a distant galaxy using a telescope above the Astronomy Tower, and you think that a rectangle drawn in that galaxy whose edges are parallel to coordinate axes and contain maximum star systems on its edges has a great deal to do with the mysteries of universe. However you do not have the laptop with you, thus you have written the coordinates of all star systems down on a piece of paper and decide to work out the result later. Can you finish this task?

Distant Galaxy UVALive - 3695 遥远的银河系 矩阵边界枚举_第1张图片

分析:部分枚举,只枚举矩形的上下边界,用其他方法确定左右边界。对于竖线i,用left[i] 表示左边位于边界上的点(不统计位于该竖线上的点,则横向边界上的点 = left[j] - left[i],i

#include 
#include 
using namespace std;
const int N = 100 + 5;
struct Point{
	int x, y;
	bool operator < (const Point &rhs){
		return x < rhs.x;
	}
}p[N];
int lefts[N], on[N], on2[N], y[N];
int solve(int n){
	sort(p, p+n);
	sort(y, y+n);
	int ans = 0, m = unique(y, y+n) - y; // 所有不同y坐标的个数
	if( m <= 2) return n; //最多有两种不同的y
	for(int a = 0; a < m; a++){
		for(int b = a+1; b < m; b++){
			int yMin = y[a], yMax = y[b]; //计算上下边界分别为yMin和yMax时的解 
			int k = 0; //标记不同的x坐标
			lefts[0] = 0;  
			for(int i = 0; i < n; i++){
				if(i == 0 || p[i-1].x != p[i].x){ //一个新的竖线 
					k++;
					on[k] = on2[k] = 0;
					lefts[k] = lefts[k-1] + on2[k-1] - on[k-1];
				}
				if(p[i].y > yMin && p[i].y < yMax){
					on[k]++;
 				}
 				if(p[i].y >= yMin && p[i].y <= yMax){
					on2[k]++;
 				}
			}
			if(k <= 2) return n; ////最多有两种不同的x
			int M = 0;
			for(int j = 1; j <= k; j++){
				ans = max(ans, lefts[j]+on2[j]+M);
				M = max(M, on[j] - lefts[j]);
			}
		}
	} 
	return ans;
}

int main(int argc, char** argv) {
	int kase = 0, n;	
	while( ~scanf("%d",&n) && n){
		for(int i = 0; i < n; i++){
			scanf("%d%d",&p[i].x,&p[i].y);
			y[i] = p[i].y;
		}
		printf("Case %d: %d\n", ++kase, solve(n));
	}
	return 0;
}

 

你可能感兴趣的:(算法竞赛入门-训练指南,acm,动态规划)