zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU4717 The Moving Points(模拟退火 || 三分法)

    Description

    There are N points in total. Every point moves in certain direction and certain speed. We want to know at what time that the largest distance between any two points would be minimum. And also, we require you to calculate that minimum distance. We guarantee that no two points will move in exactly same speed and direction.      
                  

    Input

    The rst line has a number T (T <= 10) , indicating the number of test cases.        For each test case, first line has a single number N (N <= 300), which is the number of points.        For next N lines, each come with four integers X i, Y i, VX i and VY i (-10 6 <= X i, Y i <= 10 6, -10 2 <= VX i , VY i <= 10 2), (X i, Y i) is the position of the i th point, and (VX i , VY i) is its speed with direction. That is to say, after 1 second, this point will move to (X i + VX i , Y i + VY i).      
                  

    Output

    For test case X, output "Case #X: " first, then output two numbers, rounded to 0.01, as the answer of time and distance.      
                  

    Sample Input

    2
    2
    0 0 1 0
    2 0 -1 0
    2
    0 0 1 0
    2 1 -1 0

    Sample Output

    Case #1: 1.00 0.00
    Case #2: 1.00 1.00

    题目大意就是给定n个点的坐标和它x和y方向的分速度,要求在任意时刻两两点之间距离最大值中的最小值。

    根据距离公式可以推断出对于某两个点在t逐渐增大的过程中距离服从二次函数。

    于是就是对于n个二次抛物线求任意时刻最高点合成的图像。

    可以证明(反证)合成的图像也是由两个单调性相反的图像构成(类似于抛物线)。

    于是可以采用模拟退火的退化(类似爬山算法)来查找最值。

    从minT从0时刻出发,首先设定步长dt = 1e8。然后对于minT-dt和minT+dt讨论,如果使最大值变小,自然更新minT,然后按比例k衰减dt。

    直到dt满足精度要求。

    进过测试比例k=0.9是可以满足的,跑了530MS;k = 0.95略慢些,跑了1.3S。

    网上也有好多使用的是三分法。

    这里贴出退火的代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <vector>
    #include <queue>
    #include <string>
    #define LL long long
    #define eps 1e-5
    
    using namespace std;
    
    typedef pair<double, double> pdd;
    
    int x[305], y[305], vx[305], vy[305], n;
    double minT, minDis;
    
    double pow2(double k)
    {
        return k*k;
    }
    
    double calDis(double t)
    {
        double dis2 = 0;
        for (int i = 0; i < n; ++i)
        {
            for (int j = i+1; j < n; ++j)
            {
                if (i == j)
                    continue;
                dis2 = max(dis2,
                           pow2(x[i]+vx[i]*t-x[j]-vx[j]*t) + pow2(y[i]+vy[i]*t-y[j]-vy[j]*t));
            }
        }
        return sqrt(dis2);
    }
    
    void qt()
    {
        double dt = 1e8, t, dis, k = 0.9, v;
        minT = 0;
        minDis = calDis(minT);
    
        while (dt > eps)
        {
            dis = calDis(minT+dt);
            t = minT + dt;
            if (minT-dt >= 0)
            {
                v = calDis(minT-dt);
                if (v < dis)
                {
                    dis = v;
                    t = minT - dt;
                }
            }
            if (dis < minDis)
            {
                minDis = dis;
                minT = t;
            }
            dt *= k;
        }
    }
    
    void Work()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
            scanf("%d%d%d%d", &x[i], &y[i], &vx[i], &vy[i]);
        qt();
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        int T;
        scanf("%d", &T);
        for (int times = 1; times <= T; ++times)
        {
            printf("Case #%d: ", times);
            Work();
            printf("%.2lf %.2lf
    ", minT, minDis);
        }
        return 0;
    }
  • 相关阅读:
    小小的蜗牛有大大的梦想
    Spring整合的quartz任务调度的实现方式
    HDU/HDOJ 2612 Find a way 双向BFS
    在静态库中,实现自动的初始化与卸载接口
    CF 316C2(Tidying Up-二分图最大边权)
    Qt线程同步操作用QWaitCondition QMutex
    MQ、JMS以及ActiveMQ
    微博分享利器
    discuz清空session,导致session保存机制失败,session无法更新与解决
    路由器和交换机的综合实验(1)
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4534477.html
Copyright © 2011-2022 走看看