• 「JSOI2016」炸弹攻击(模拟退火)


    https://loj.ac/problem/2076

    模拟退火居然不出题答,这个出题人脑子进水了。

    由最小圆覆盖那一套,最优的圆是以上三种情况之一:
    1.一个答案点就是圆,半径—>0
    2.两个点连成的线段为直径的圆
    3.三点共园

    直接枚举,判断是(O(m^4))的。
    可能可以优化掉一个(m),然后你发现做不下去了。

    考虑退火,这个题直接以覆盖的点数作为价值退火是不太行的。

    当价值相同时,应取当前圆的最大半径作为第二关键字。

    然后调整发现,应该使往劣的方向走的概率变小。

    这么个连样例都吃力的做法它能过。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    #define db double
    
    const int N = 1005;
    
    int n, m;
    db R, r[N];
    
    struct P {
    	db x, y;
    	P(db _x = 0, db _y = 0) {
    		x = _x, y = _y;
    	}
    } a[N], b[N];
    
    #define sqr(x) ((x) * (x))
    db dis(P a, P b) {
    	return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
    }
    
    ll rand(ll x, ll y) {
    	return ((ll) RAND_MAX * rand() + rand()) % (y - x + 1) + x;
    }
    
    db rd() {
    	return (db) rand(0, 1e8) / 1e8;
    }
    
    const db eps = 1e-8;
    
    P calc(P c) {
    	db mi = R;
    	fo(i, 1, n) mi = min(mi, dis(a[i], c) - r[i]);
    	int s = 0;
    	fo(i, 1, m) s += dis(c, b[i]) <= mi;
    	return P(s, mi);
    }
    
    int main() {
    	srand(time(0) + clock());
    	scanf("%d %d %lf", &n, &m, &R);
    	fo(i, 1, n) scanf("%lf %lf %lf", &a[i].x, &a[i].y, &r[i]);
    	fo(i, 1, m) scanf("%lf %lf", &b[i].x, &b[i].y);
    	int ans = 0;
    	fo(ii, 1, min(50000 / m, 1000)) {
    		P c = b[rand(1, m)];
    		for(db T = 100; T > eps; T *= 0.99) {
    			P d = c;
    			d.x += (rd() - 0.5) * T * (R / 200), d.y += (rd() - 0.5) * T * (R / 200);
    			P v1 = calc(c), v2 = calc(d);
    			ans = max(ans, (int) v2.x);
    			if(v2.x > v1.x) {
    				c = d;
    				continue;
    			}
    			if(v1.x == v2.x) {
    				if(v2.y > v1.y) {
    					c = d;
    					continue;
    				}
    				if(exp((db) (v2.y - v1.y) / T) / 10 * 1e9 > rand(1, 1e9)) {
    					c = d;
    				}
    				continue;
    			}
    			if(exp((db) (v2.x - v1.x) / T) / 10 * 1e9 > rand(1, 1e9)) {
    				c = d;
    			}
    		}
    	}
    	
    	pp("%d
    ", ans);
    }
    
  • 相关阅读:
    06.章节页面接口开发
    05.课程主页面三个接口开发
    python高级(六)——用一等函数实现设计模式
    python高级(五)—— python函数(一等对象)
    python高级(四)—— 文本和字节序列(编码问题)
    python高级(三)—— 字典和集合(泛映射类型)
    python高级——目录
    python高级(二)—— python内置序列类型
    python高级(一)—— python数据模型(特殊方法)
    python实现百度地图API获取某地址的经纬度
  • 原文地址:https://www.cnblogs.com/coldchair/p/12734643.html
Copyright © 2020-2023  润新知