POJ 1054 暴力

题意

传送门 POJ 1054

题解

枚举顶点对作为线段端点 O ( n 2 ) O(n^2) O(n2) ,只有线段最长的边才是可能解;以端点间距为步长,通过判断端点是否在边界上(路径横穿地图),即可判断是否需要从另一个端点开始统计点数;若一开始使顶点有序,可只判断一侧端点。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define abs(x)    ((x) < 0 ? -(x) : (x))
#define INF 0x3f3f3f3f3f3f3f3f
#define delta 0.85
using namespace std;

struct P{
	int x, y;
	P(){}
	P(int x, int y) : x(x), y(y) {}
	P operator + (P p){
		return P(x + p.x, y + p.y);
	}
	P operator - (P p){
		return P(x - p.x, y - p.y);
	}
	P operator * (int d){
		return P(x * d, y * d);
	}
	bool operator < (const P& p) const{
		if(x == p.x){
			return y < p.y;
		}
		return x < p.x;
	}
};

#define maxn 5005
int R, C, N;
bool mp[maxn][maxn];
P ps[maxn];

void solve(){
	sort(ps, ps + N);
	int res = 0;
	for (int i = 0; i < N; i++){
		for (int j = i + 1; j < N; j++){
			P step = ps[i] - ps[j], pre = ps[i] + step;
			// 非最长线段端点
			if(pre.x > 0 && pre.x <= R && pre.y > 0 && pre.y <= C){
				continue;
			}
			P tmp = ps[j] - step * res;
			// 非最优解
			if(!(tmp.x > 0 && tmp.x <= R && tmp.y > 0 && tmp.y <= C)){
				continue;
			}
			int cnt = 0;
			P nxt = ps[j] - step;
			while(nxt.x > 0 && nxt.x <= R && nxt.y > 0 && nxt.y <= C && mp[nxt.x][nxt.y]){
				++cnt;
				nxt = nxt - step;
			}
			if(nxt.x > 0 && nxt.x <= R && nxt.y > 0 && nxt.y <= C){
				cnt = 0;
			}
			res = max(res, cnt);
		}
	}
	printf("%d\n", res == 0 ? 0 : res + 2);
}

int main(){
	while(~scanf("%d%d", &R, &C)){
		scanf("%d", &N);
		memset(mp, 0, sizeof(mp));
		for (int i = 0; i < N; i++){
			int x, y;
			scanf("%d%d", &x, &y);
			ps[i] = P(x, y);
			mp[x][y] = 1;
		}
		solve();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值