zoukankan      html  css  js  c++  java
  • 洛谷 SP34 RUNAWAY

    SP34 RUNAWAY - Run Away

    这道题和那道平衡点吊打XXX有点像。

    不同的是那道题中的每个点都有权值,而这道题没有,然后求的东西也不太一样,不过万变不离其宗,还是可以用模拟退火做。
    
    而且这道题的数据比较弱,所以随便调参基本都可以过,不像其他题目的参数极度看脸, 是一道对欧洲人与非洲人都十分友好的模拟退火入坑题。
    具体步骤见下面代码注释:
    

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    //Mystery_Sky
    //
    #define M 1000100
    #define INF 0x3f3f3f3f
    struct node{
    	int x, y;
    }point[M];
    int t, n, X, Y;
    const double delta = 0.993;//降温系数
    double ans_x, ans_y;
    
    inline double dist(double x, double y)//求出题中要求的距离所有点的最小值
    {
    	double maxx = INF;
    	for(int i = 1; i <= n; i++) {
    		double dx = point[i].x - x;
    		double dy = point[i].y - y;
    		double dis = sqrt(dx * dx + dy * dy);
    		maxx = min(dis, maxx);
    	}
    	return maxx;
    }
    
    inline void SA()
    {
    	double x = ans_x, y = ans_y;
    	double T = 2000;//初始温度。
    	double Ans = 0;
    	while(T > 1e-14) {
    		double new_x = x + ((rand()<<1) - RAND_MAX) * T;
    		double new_y = y + ((rand()<<1) - RAND_MAX) * T;
    		if(new_x > X || new_y > Y || new_x < 0 || new_y < 0) {//若随机出的新答案不在题目约束的范围内,则跳过后续部分,重新生成新解。
    			T *= delta;
    			continue;
    		}
    		double new_ans = dist(new_x, new_y);
    		double DE = Ans - new_ans;
    		if(DE < 0) {//如果生成的新答案比之前得到的最优解更大,则接受这个新答案。
    			ans_x = x = new_x;
    			ans_y = y = new_y;
    			Ans = new_ans;
    		}
    		else if(exp(-DE/T) * RAND_MAX > rand()) x = new_x, y = new_y;//否则以一定的概率接受这个新答案(模拟退火不同于爬山算法之处)。
    		T *= delta;//降温。
    	}
    	
    }
    
    int main() {
    	srand(19260817);
        srand(rand());
        srand(rand());//玄学种子
    	scanf("%d", &t);
    	while(t--) {
    		int sum_x = 0;
    		int sum_y = 0;
    		scanf("%d%d%d", &X, &Y, &n);
    		for(int i = 1; i <= n; i++) {
    			scanf("%d%d", &point[i].x, &point[i].y);
    			sum_x += point[i].x;
    			sum_y += point[i].y;	
    		}
    		ans_x = (double)sum_x / n;
    		ans_y = (double)sum_y / n;//沿用平衡点吊打XXX那道题的做法,继续使用所有点的平均值的点作为初始的答案。
    		SA();
    		SA();
    		SA();
    		printf("The safest point is (%.1lf, %.1lf).
    ", ans_x, ans_y);	
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    链式栈的C++实现
    Java面试之设计模式二
    前端资源
    Java面试之异常
    Java面试之序列化
    Java面试之重写(Override)与重载(Overload)
    项目视图展示
    Java面试之集合
    Java面试之SSH框架面试题集锦
    JDBC技术
  • 原文地址:https://www.cnblogs.com/Benjamin-cpp/p/11153879.html
Copyright © 2011-2022 走看看