POJ 3347 (思维、计算几何)

题目链接:http://poj.org/problem?id=3347


题意:给予n个正方形,要求45°角放置,最左边的正方形紧贴Y轴,所有的正方形的下面的端点都在X轴上。然后按照正方形不能交错但要尽可能的挨着的原则,摆放,最后输出从上往下看能看到的正方形的编号。正方形必须要按照顺序摆放。


参考博客:http://www.cnblogs.com/tmeteorj/archive/2012/10/19/2731024.html


题解:1、假如前i-1个正方形位置都确定了,那么可以让第i个正方形与前i-1个正方形每个都计算一次它如果和它相依靠的话左边坐标的值,然后取一个最大的便是这个正方形的左端点位置。
2、对于j<i的正方形,如果i的边长大于j那么j的最右能看到的部分就不会比i的最左端点大,反之,i的最左能看到的部分就不会比j最右端点小。
3、通过第2步筛选,将那些最左能看到的端点比最右能看到端点大或等于的去掉,剩下的就是所要求的。


注意最后的精度问题,开始把所有长度乘以sqrt(2)应该就可以避免精度问题。


#include <iostream> 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = 1e-8;
struct m {
	double len, l, r;
};
m sq[55];
int main() {
	int n;
	while(~scanf("%d", &n) , n) {
		int i, j;
		for(i = 1; i <= n; i++) {
			scanf("%lf", &sq[i].len);
			sq[i].l = 0;
			for(j = 1; j < i; j++) {
				sq[i].l = max(sq[i].l, sq[j].r - fabs(sq[i].len - sq[j].len) / sqrt(2.0));
			}
			sq[i].r = sq[i].l + sq[i].len * sqrt(2.0);
		}
		//更新所有正方形的可见左右端点。因为并不知道每个正方形的相对位置,所以直接遍历一遍即可 
		for(i = 1; i <= n; i++) {
			for(j = 1; j < i; j++) {
				if(sq[i].len > sq[j].len && sq[i].l < sq[j].r) sq[j].r = sq[i].l;
				if(sq[i].len < sq[j].len && sq[i].l < sq[j].r) sq[i].l = sq[j].r;
			}
		}
		int flag = 1;
		for(i = 1; i <= n; i++) {
			if(sq[i].l < sq[i].r - eps) {   //精度问题,不加eps会wa 
				if(flag) flag = 0;
				else printf(" ");
				printf("%d", i);
			}
		}
		puts("");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值