ZOJ 3238 Water Ring(暴力...)

来源:互联网 发布:软件项目进度管理 编辑:程序博客网 时间:2024/06/03 22:46

题意:

有一个圆,半径为R,圆心在坐标原点,有n个长方形的条子,左下角的坐标是x1,y1,右上角坐标是x2,y2,然后长方条有些覆盖圆的弧,求圆的所有被长方条覆盖的弧的长度


一开始的想法是把每个长方条覆盖的圆相交的区间找出来,然后再合并,写了几行代码后就觉得判断各种情况太麻烦了= =!果断不想写

然后就想到把圆的边分为很多很多份,取每份弧的中点,判断它是不是在长方条内,如果是的话,就当那段弧在长方条内,但是这样做精度不够,wa了好多次

最后就想到把圆的边分为很多很多份,然后判断每份的左端点和右端点是不是在长方条内,如果都在的话就加上这段弧的边上,都不在的话就不加,一个在一个不在的话就二分找出这段弧和长方条的交点,然后加上相交的弧长。这里假设它是没有一段弧和长方条的一个角相交,就是左端点和右端点都不在长方条内,但是弧内有一段是在长方条内,因为每一段弧都很小,而且长方条坐标都是整数,出现这种情况不容易 - -!

虽然wa了11次,但是看到别人代码的各种长还是挺happy的偷笑


#include<iostream>#include<cstdio>#include<cstring>#include<set>#include<string>#include<cmath>#include<algorithm>#include<queue>#include<map>#include<vector>using namespace std;#define eps 1e-10#define LL long long#define inf 0x3f3f3f3fconst double PI = acos( -1.0 );#define mxn 500 // 这里mxn就是把圆分为多少分, 刚开始时15W,后来发现数据水,500都可以 - -!!!!!struct node {double x, y, x3, y3;void input() {scanf( "%lf%lf%lf%lf", &x, &y, &x3, &y3 );}}a[500];double r;int n;bool in( double x ) {   // 判断圆上极角为x(弧度)的是不是在长方条内double xx = r * cos( x ), yy = r * sin( x );for( int i = 1; i <= n; ++i ) {if( a[i].x <= xx && a[i].x3 >= xx && a[i].y <= yy && a[i].y3 >= yy )return 1;}return 0;}int main() {//freopen( "tt.txt", "r", stdin );while( scanf( "%lf%d", &r, &n ) != EOF ) {for( int i = 1; i <= n; ++i )a[i].input();double len = 2 * PI * r / mxn;double ans = 0;double k = 2 * PI / mxn;for( int i = 0; i < mxn; ++i ) {double head = k * i, tail = k * ( i + 1 );bool ok1 = in( head );bool ok2 = in( tail );if( ok1 && ok2 ) {ans += len;continue;}if( !ok1 && !ok2 ) {continue;}if( ok1 ) {double rr = head;while( tail - head > eps ) {double mid = ( head + tail ) / 2;if( in( mid ) )head = mid;elsetail = mid;}ans += ( tail - rr ) / k * len;}else {double rr = tail;while( tail - head > eps ) {double mid = ( head + tail ) / 2;if( in( mid ) )tail = mid;elsehead = mid;}ans += ( rr - head ) / k * len;}}printf( "%.3lf\n", ans );}return 0;}



0 0
原创粉丝点击