首页 > 代码库 > POJ 1379 Run Away(模拟退火)

POJ 1379 Run Away(模拟退火)

模拟退火的步骤:

确定初始解集S和控制参数初值delta开始,对当前解重复的产生新解,并选择接受或舍弃,并逐步衰减delta值,算法终止后可以得到一组解集。答案可以最终解集的最优解。

对于这道题,选择矩形内的一点,使得满足与给定点集的最小距离最大。同样可以用模拟退火算法来解决。

 

技术分享
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi 3.1415926535
# define eps 1e-3
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
void Out(int a) {
    if(a<0) {putchar(-); a=-a;}
    if(a>=10) Out(a/10);
    putchar(a%10+0);
}
const int N=100005;
//Code begin...

struct Node{double x, y;}node[1005], now[15], tmp, tt, ans;
int m;
double d[15], total;

inline double Rand(){return (rand()%1000+1)/1000.0;}
inline double dis(Node a, Node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline double cal(Node p){
    double res=INF;
    FOR(i,1,m) res=min(res,dis(p,node[i]));
    return res;
}
int main ()
{
    srand(10086);
    int T, x, y;
    scanf("%d",&T);
    while (T--) {
        total=0;
        scanf("%d%d%d",&x,&y,&m);
        FOR(i,1,m) scanf("%lf%lf",&node[i].x,&node[i].y);
        FOR(i,1,10) {
            now[i].x=Rand()*x; now[i].y=Rand()*y;
            d[i]=INF; FOR(j,1,m) d[i]=min(d[i],dis(now[i],node[j]));
        }
        double Tc=10000, alpha, v;
        while (Tc>eps) {
            FOR(i,1,10) {
                tmp=now[i];
                FOR(j,1,30) {
                    alpha=2.0*pi*Rand();
                    tt.x=tmp.x+Tc*cos(alpha); tt.y=tmp.y+Tc*sin(alpha);
                    if (tt.x<0||tt.x>x||tt.y<0||tt.y>y) continue;
                    if ((v=cal(tt))>d[i]) d[i]=v, now[i]=tt;
                }
            }
            Tc*=0.9;
        }
        total=0;
        FOR(i,1,10) if (total<d[i]) total=d[i], ans=now[i];
        printf("The safest point is (%.1f, %.1f).\n",ans.x,ans.y);
    }
    return 0;
}
View Code

 

POJ 1379 Run Away(模拟退火)