hdu 3644(几何模拟退火

传送门




A Chocolate Manufacturer's Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2360    Accepted Submission(s): 456


Problem Description
My mama always said:Life is like a box of chocolate, you never know what you are going to get. 
——From Forrest Gump


ACM is a chocolate manufacturer. Inspired by the famous quote above, recently, they are designing a new brand of chocolate named Life. Each piece of chocolate is a random simple polygon. After molding and shaping, every piece is put in a small box. Until you open the box, you will not know what you will get: a huge piece or only a tiny fraction. It is really like life and that is the reason it is named for.

However, here comes a problem. The manufacturer has to print the logo on each piece of chocolate. The logo is a circle with ‘ACM’ inside. Here is an example below. It is fortunate that the logo can be printed on the chocolate.

Now the manufacturer is asking you for help. Given the information about the chocolate shape and the radius of the logo, you need to judge whether or not there is enough space to print the logo.
 

Input
The input contains no more than 20 cases, and each case is formatted as follows.

x 1 y 1 
x 2 y 2

x n y n 
r
The first line is the number of vertices of the polygon, n, which satisfies 3 ≤ n ≤ 50. Following n lines are the x- and y-coordinates of the n vertices. They are float numbers and satisfy 0 ≤ x i ≤ 1000 and 0 ≤ y i ≤ 1000 (i = 1, …, n). Line segments (x i, y i)–(x i+ 1 , y i + 1) (i = 1, …, n) and the line segment (x n, y n)–(x 1, y 1) form the border of the polygon. After the description of the polygon, a float number r follows, meaning the radius of the logo( r <= 1000). 
The input ends by a single zero.
You may assume that the polygon is simple, that is, its border never crosses or touches itself.
 

Output
For each case, output “Yes” if the logo is able to be printed on the chocolate, otherwise output “No” instead.
 

Sample Input
      
      
3 0 0 0 1 1 0 0.28 3 0 0 0 1 1 0 0.3 0
 

Sample Output
      
      
Yes No
Hint
Here is a picture illustrated the first case. It may be helpful for you to understand the problem.
 

Source

题意:n。n个点。问这些点连起来的多边形(可能是凹的 能不能有一个R半径的圆的面积。

明显在多边形里求一个点到这个多边形所有边的距离能<=R肯定就Yes。

必须保证点在这个多边形内。

有多种方法可以判断,个人喜好。

//china no.1
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <complex>
#include <sstream>
#include <time.h>
#include <functional>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,-1,-1,1,1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
const int maxn=1e3+5;
//const int maxx=1e5+100;
const double EPS=1e-7;
const double eps=1e-5;
const int MOD=10000007;
#define mod(x) ((x)%MOD);
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
//typedef tree<pt,null_type,less< pt >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
long long gcd(long long a , long long b){if(b==0) return a;a%=b;return gcd(b,a);}
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while

inline int Scan()
{
    int res=0,ch,flag=0;
    if((ch=getchar())=='-')flag=1;
    else if(ch>='0' && ch<='9')res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';
    return flag ? -res : res;
}
int n;

struct point
{
    double x, y, r;
} p[maxn], test[maxn];
inline int dblcmp( double x )
{
    if( fabs(x) < eps )
        return 0;
    return x > 0 ? 1 : -1;
}

inline double sqr( double x )
{
    return x*x;
}
/*
double X(point A,point B,point C)//差积 是否<0
{
    return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
}
double len(point A,point B)//距离
{
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

bool cmp(point A,point B)
{
    double pp=X(p[0],A,B);
    if(pp>0)  return 1;
    if(pp<0)  return 0;
    return len(p[0],A)<len(p[0],B); //如果等于0 判断距离  返回小的
}
*/
double dis( point& aa, point& bb )
{
    return sqrt(sqr(aa.x-bb.x)+sqr(aa.y-bb.y));
}

double cross( point& k, point& aa, point& bb )
{
    return (k.x-aa.x)*(k.y-bb.y)-(k.y-aa.y)*(k.x-bb.x);
}

//线段到点的距离
double seg_point_dis( point& l1, point& l2, point& k )
{
    double a, b, c;
    a = dis(l1, k);
    b = dis(l2, k);
    c = dis(l1, l2);

    //这里的判断是由余弦定理推出来的
    if( dblcmp(a*a+c*c-b*b) < 0 )
        return a;
    else if( dblcmp(b*b+c*c-a*a) < 0 )
        return b;
    else
        return fabs(cross(k, l1, l2)/c);
}
/*
double cal( point& t )
{
    double maxc=INF;
    for(int i=0; i<n; i++)
    {
        double z = seg_point_dis(p[i], p[i+1], t);
        maxc = min(maxc, z);
    }
    return maxc;
}*/
void cal( point& aa )
{
    double t;
    aa.r = INF;
    for( int i = 0; i < n; ++i )
    {
        t = seg_point_dis(p[i], p[i+1], aa);
        aa.r = min(aa.r, t);
    }
}

bool point_inside( point& aa )
{
    int i, cnt = 0;
    double t;

    //确保p[n] = p[0]
    for( i = 0; i < n; ++i )
    {
        if( (p[i].y <= aa.y && p[i+1].y > aa.y) ||
            (p[i+1].y <= aa.y && p[i].y > aa.y) )
        {
            if( !dblcmp(p[i].y-p[i+1].y) )
            {
                if( dblcmp(p[i].y-aa.y) == 0 )
                    cnt++;
                t = -INF;
            }
            else
                t = p[i+1].x - (p[i+1].x-p[i].x)*(p[i+1].y-aa.y)/(p[i+1].y-p[i].y);

            if( dblcmp( t - aa.x ) >= 0 )
                cnt++;
        }
    }

    return cnt%2;
}

double maxx, maxy, minx, miny,R;
//double r=0.8;
int main()
{
    srand();

    while( scanf("%d", &n), n )
    {
        int init_num=20;
        int i, j;
        maxx = maxy = 0;
        minx = miny = INF;
        for(i=0; i<n ;i++)
        {
            scanf("%lf %lf", &p[i].x, &p[i].y);
            maxx = max(maxx, p[i].x);
            maxy = max(maxy, p[i].y);
            minx = min(minx, p[i].x);
            miny = min(miny, p[i].y);
        }
        maxx -= minx;    maxy -= miny;
        p[n] = p[0];
         for( i = 0; i < init_num; ++i )
        {
            test[i].x = (p[i].x+p[i+1].x)/2;
            test[i].y = (p[i].y+p[i+1].y)/2;
            test[i].r = 0;
        }
        scanf("%lf", &R);
        int ok=0;
        point next, temp;
        double step=sqrt(maxx*maxx+maxy*maxy)/2;
        //double step=double(max(maxx,maxy)/sqrt(1.0*n));//初始步长长度
        while( !ok && step > eps )
        {
            for( i = 0; !ok && i < init_num; ++i )
            {
                for( j = 0; !ok && j < 50; ++j )
                {
                    double ang=(rand()%1000+1)/1000.0*2*pi;
                    temp.x = test[i].x + step*cos(ang);
                    temp.y = test[i].y + step*sin(ang);
                    if( point_inside(temp) )
                    {
                        cal(temp);
                        if( temp.r > test[i].r )
                        {
                            test[i] = temp;
                            if( dblcmp(temp.r-R) >= 0 )
                                ok = 1;
                        }
                    }
                }
            }
            step *= 0.50;
        }

        if(ok)
            printf("Yes\n");
        else printf("No\n");
    }
}


A Chocolate Manufacturer's Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2360    Accepted Submission(s): 456


Problem Description
My mama always said:Life is like a box of chocolate, you never know what you are going to get. 
——From Forrest Gump


ACM is a chocolate manufacturer. Inspired by the famous quote above, recently, they are designing a new brand of chocolate named Life. Each piece of chocolate is a random simple polygon. After molding and shaping, every piece is put in a small box. Until you open the box, you will not know what you will get: a huge piece or only a tiny fraction. It is really like life and that is the reason it is named for.

However, here comes a problem. The manufacturer has to print the logo on each piece of chocolate. The logo is a circle with ‘ACM’ inside. Here is an example below. It is fortunate that the logo can be printed on the chocolate.

Now the manufacturer is asking you for help. Given the information about the chocolate shape and the radius of the logo, you need to judge whether or not there is enough space to print the logo.
 

Input
The input contains no more than 20 cases, and each case is formatted as follows.

x 1 y 1 
x 2 y 2

x n y n 
r
The first line is the number of vertices of the polygon, n, which satisfies 3 ≤ n ≤ 50. Following n lines are the x- and y-coordinates of the n vertices. They are float numbers and satisfy 0 ≤ x i ≤ 1000 and 0 ≤ y i ≤ 1000 (i = 1, …, n). Line segments (x i, y i)–(x i+ 1 , y i + 1) (i = 1, …, n) and the line segment (x n, y n)–(x 1, y 1) form the border of the polygon. After the description of the polygon, a float number r follows, meaning the radius of the logo( r <= 1000). 
The input ends by a single zero.
You may assume that the polygon is simple, that is, its border never crosses or touches itself.
 

Output
For each case, output “Yes” if the logo is able to be printed on the chocolate, otherwise output “No” instead.
 

Sample Input
       
       
3 0 0 0 1 1 0 0.28 3 0 0 0 1 1 0 0.3 0
 

Sample Output
       
       
Yes No
Hint
Here is a picture illustrated the first case. It may be helpful for you to understand the problem.
 

Source

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值