POJ 1379 Run Away(模拟退火)
模拟退火的步骤:
确定初始解集S和控制参数初值delta开始,对当前解重复的产生新解,并选择接受或舍弃,并逐步衰减delta值,算法终止后可以得到一组解集。答案可以最终解集的最优解。
对于这道题,选择矩形内的一点,使得满足与给定点集的最小距离最大。同样可以用模拟退火算法来解决。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 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; }