Poj1379(模拟退火

题目:在矩形中有若干个点,求一个点使得所有点到该点的最小距离最大。

思路:这个是2008年顾研论文上的例题,可以比较简单地用模拟退火算法求解。所谓模拟退火就是先随机出若干个点,然后以某一特定步长尝试周围的解,而后逐渐缩小步长,知道步长小于特定值,跳出。这个算法虽然简单易行,但是其正确性并不是非常有保障,(不合理的随机方法可能会降低到达正确解的概率),而且几个主要参数的选取也主要看经验,毕竟对于一个随机化算法做出像论文中一样的严格评估还是比较困难的。。。。所以说即使实现完全正确,能否通过有时也是玄学的领域。。。。。尤其对于不太适合随机化的题。

ps:poj不能用time,一调用就re,查了一个多小时错才发现。。。。以后不用time了。。。

/*
* @author:  Cwind
* http://www.cnblogs.com/Cw-trip/
* 蒟蒻只能做几个水题。。
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-3)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define FINF (1e100)
#define INF 1000000000
const double pi=acos(-1.0);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

inline double dis(double x1,double y1,double x2,double y2){
    return sqrt(sq(x1-x2)+sq(y1-y2));
}
int T;
int X,Y,M;
const int L=30;
double zx[1005],zy[1005];
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    srand(rand()%100);
    cin>>T;
    while(T--){
        cin>>X>>Y>>M;
        double delta=max(X,Y)/sqrt(M*1.0)+1,pos[30][2],d[30];
        for(int i=0;i<M;i++){
            double x,y;
            scanf("%lf%lf",&x,&y);
            zx[i]=x,zy[i]=y;
        }
        for(int i=0;i<30;i++){
            pos[i][0]=(rand()%(1000+1)/1000.0*X);
            pos[i][1]=(rand()%(1000+1)/1000.0*Y);
            d[i]=FINF;
            for(int j=0;j<M;j++){
                d[i]=fmin(d[i],dis(pos[i][0],pos[i][1],zx[j],zy[j]));
            }
        }
        while(delta>eps){
            for(int i=0;i<30;i++){
                for(int j=0;j<L;j++){
                    double rd=rand();
                    double dx=pos[i][0]+cos(rd)*delta,dy=pos[i][1]+sin(rd)*delta;
                    if(dx>X||dx<0||dy>Y||dy<0) continue;
                    double md=FINF;
                    for(int k=0;k<M;k++){
                        md=fmin(md,dis(dx,dy,zx[k],zy[k]));
                    }
                    if(md>d[i]){
                        pos[i][0]=dx;
                        pos[i][1]=dy;
                        d[i]=md;
                    }
                }
            }
            delta*=0.8;
        }
        double ans=0;
        int ansp=0;
        for(int i=0;i<30;i++){
            if(ans<d[i]){
                ans=d[i];
                ansp=i;
            }
        }
        printf("The safest point is (%.1f, %.1f).\n",pos[ansp][0],pos[ansp][1]);
    }
    return 0;
}

时间: 2024-11-01 17:51:15

Poj1379(模拟退火的相关文章

poj1379 模拟退火

1 //Accepted 220 KB 829 ms 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cstdlib> 7 #include <iostream> 8 using namespace std; 9 const int iL=30; 10 const int iP=30; 11 const

poj1379模拟退火

题意: 求一个点到给出点最短距离最长的那个点. 看rp  迭代次数越多和 初始随机点越多 应该越准确(初始随机点坑了,多了也不一定准确). #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include &l

【模拟退火】poj1379 Run Away

题意:平面上找一个点,使得其到给定的n个点的距离的最小值最大. 模拟退火看这篇:http://www.cnblogs.com/autsky-jadek/p/7524208.html 这题稍有不同之处仅有:多随机几个初始点,以增加正确率. 另:WA了几百遍竟然是因为最后输出了-0.0这样的值…… #include<cstdio> #include<cmath> #include<algorithm> #include<cstdlib> using namesp

【POJ1379】Run Away 模拟退火

#include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/43526827"); } 题意: 给若干个点,现在求一个点,使它到离它最近的点尽量远. 题解: 我写的是模拟退火先玩一会,然后小幅度爬爬山. 种子的采用是20134858 是生日^人的名字首字母hash. 诶可算A了,看来我脸还不是太黑. 代

poj-2420 A Star not a Tree?(模拟退火算法)

题目链接: A Star not a Tree? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5219   Accepted: 2491 Description Luke wants to upgrade his home computer network from 10mbs to 100mbs. His existing network uses 10base2 (coaxial) cables that allo

POJ 3087 Shuffle&#39;m Up(模拟退火)

Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of poker chips, S1 and S2, each stack containing C chips. Each stack may contain chips of several

PKU 1379 Run Away(模拟退火算法)

题目大意:原题链接 给出指定的区域,以及平面内的点集,求出一个该区域内一个点的坐标到点集中所有点的最小距离最大. 解题思路:一开始想到用随机化算法解决,但是不知道如何实现.最后看了题解才知道原来是要用模拟退火算法解决. 不过个人感觉这个算法的实现过程中仍然采用了随机化算法.二者均属于概率算法.  参考链接 Point Goto_Rand_Dir(double key,Point temp)函数中,Point temp必须得定义在参数中,不能定义在函数内部, 否则temp没有初始值,无法进行后面的

[POJ2069]Super Star(模拟退火)

题目链接:http://poj.org/problem?id=2069 题意:求一个半径最小的球,使得它可以包围住所有点. 模拟退火,圆心每次都去找最远那个点,这样两点之间的距离就是半径,那么接下来移动的方向肯定就是朝着这个最远点移动,保证比例相同且在球内的情况下移动. 不看题解想不到,这个东西有点难啊... 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <

两种改进的模拟退火算法求解大值域约束满足问题1.0

0引言 约束满足问题(Constraint Satisfaction Problem,CSP)是人工智能研究领域中一个非常重要的分支,现已成为理论计算机科学.数学和统计物理学等交叉学科研究中的热点问题.人工智能.计算机科学和自动控制等领域中的许多问题都可以归结为约束满足问题.同时,约束满足问题在实际问题如模式识别.决策支持.物流调度及资源分配等领域也有着非常广泛的应用. CSP由一个变量集合和一个约束集合组成.每个变量都有一个非空的可能值域,每个约束描述了一个变量子集与子集内各变量的相容赋值,所