absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] [-30] 100324 A
[破碎的状态] [-29] Codeforces 2C

[破碎的状态] [-30] Hdu 3644

absi2011 posted @ Jun 22, 2016 05:40:13 PM in 刷题记录 with tags HDU 模拟退火 模拟 瞎搞 小高考 , 577 阅读

生活就像一块巧克力,有时是WA型,有时是TLE型,你永远不知道你会得到哪一种

这道退火做的还是挺伤的..

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3644

感谢@JCarlson 翻译,题意摘自翻译:

巧克力加工者的问题
由于一条沙茶到极点的名言使得最近的巧克力加工者脑子不正常。他们创造出了一种新的巧克力叫做“生活”。这种畸形巧克力都是多边形,它们做好以后就被装到盒子里,因此直到你打开这个盒子你是不知道会拿到什么样的巧克力的。这就和生活一样你永远不知道未来会发生什么,这样想来这个巧克力貌似还挺有哲理的。
然而出现了一个问题,巧克力加工者需要把他们的圆形标志印在巧克力上头。现在告诉你这个巧克力的形状,以及圆形的半径,你需要判断这个标志能否印在这个巧克力上。

所以我们设置R,表示到所有点/边的距离的最小值..

这时候就考验数学功底什么的了..

感谢@MengCl3 教我数学..

使用点积算出角度是否是钝角..钝角就算点到点的距离,不然算点到直线距离..

一直WA或者TLE..就像开头的那块巧克力..

后来发现..

卡常数是第一生产力..只有卡好常数..你才能多退几次..多退几次你才能AC..

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct point
{
    double x;
    double y;
    void read()
    {
        scanf("%lf%lf",&x,&y);
    }
    point (double xx=0,double yy=0)
    {
        x=xx;
        y=yy;
    }
    friend point operator - (const point &a,const point &b)
    {
        return point(a.x-b.x,a.y-b.y);
    }
    friend double operator * (const point &a,const point &b)
    {
        return a.x*b.y-a.y*b.x;
    }
    double dis(point &a)
    {
        return (x-a.x)*(x-a.x)+(y-a.y)*(y-a.y);
    }
    double distance_2(point &a,point &b)
    {
        double t=point(a.x-x,a.y-y)*point(b.x-x,b.y-y);
        return t*t/a.dis(b);
    }
    double multi_dot(point a)
    {
        return x*a.x+y*a.y;
    }
};
point a[55];
const double eps=1e-5;
int n;
double cross(point &a,point &b,point &c,point &d)
{
    if (((a-c)*(a-d))*((b-c)*(b-d))>=0) return false;
    if (((c-a)*(c-b))*((d-a)*(d-b))>=0) return false;
    return true;
}
double get_val(point &a,point &b,point &c)
{
    if ((a-b).multi_dot(c-b)<=0) return a.dis(b);
    if ((a-c).multi_dot(b-c)<=0) return a.dis(c);
    return a.distance_2(b,c);
}
bool try_best_ans(double expect_ans)
{
    double t=1e-6;
    double size=50;
    int temp=rand()%n;
    double x=a[temp].x;
    double y=a[temp].y;
    double cur_ans=0;
    for (;;)
    {
        if (size<1e-8) return false;
        double s=(double)rand()/RAND_MAX-0.5;
        double deltax=s*size*2;
        s=(double)rand()/RAND_MAX-0.5;
        double deltay=s*size*2;
        size*=0.99;
        double newx=x+deltax;
        double newy=y+deltay;
        point now_point=point(newx,newy);
        bool flag=0;
        int i;
        for (i=0;i<n;i++)
        {
            /*
            if (a[i].x==newx)
            {
                if (a[i+1].x<=newx) flag^=1;
                if (a[i+1].x!=newx) continue;
            }
            if (a[i+1].x==newx)
            {
                if (a[i].x<=newx) flag^=1;
                continue;
            }*/
            point t=point(newx,1e18);
            if (cross(now_point,t,a[i],a[i+1])) flag^=1;
        }
        if (flag==0) continue;
        double mins=1e18;
        for (i=0;i<n;i++)
        {
            mins=min(mins,get_val(now_point,a[i],a[i+1]));
        }
        if (mins+eps>=expect_ans)
        {
            return true;
        }
        if (mins>cur_ans)
        {
            cur_ans=mins;
            x=newx;
            y=newy;
        }
        else
        {
            if (exp((mins-cur_ans)/t)*RAND_MAX>rand())
            {
                cur_ans=mins;
                x=newx;
                y=newy;
            }
            t*=0.99;
        }
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    srand(2011719);
    for (;;)
    {
        scanf("%d",&n);
        if (n==0) break;
        int i;
        for (i=0;i<n;i++)
        {
            a[i].read();
        }
        a[i]=a[0];
        double r;
        scanf("%lf",&r);
        for (i=0;i<30;i++)
        {
            if (try_best_ans(r*r))
            {
                puts("Yes");
                break;
            }
        }
        if (i==30)
        {
            puts("No");
        }
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter