【模拟退火\爬山算法】[HYSBZ/BZOJ3680]吊打XXX(吊打GTY)
2016-06-24 00:24
393 查看
题目描述
Description
gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty。gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了。蒟蒻们将n个gty吊在n根绳子上,每根绳子穿过天台的一个洞。这n根绳子有一个公共的绳结x。吊好gty后蒟蒻们发现由于每个gty重力不同,绳
结x在移动。蒟蒻wangxz脑洞大开的决定计算出x最后停留处的坐标,由于他太弱了决定向你求助。
不计摩擦,不计能量损失,由于gty足够矮所以不会掉到地上。
Input
输入第一行为一个正整数n(1<=n<=10000),表示gty的数目。接下来n行,每行三个整数xi,yi,wi,表示第i个gty的横坐标,纵坐标和重力。
对于20%的数据,gty排列成一条直线。
对于50%的数据,1<=n<=1000。
对于100%的数据,1<=n<=10000,-100000<=xi,yi<=100000
Output
输出1行两个浮点数(保留到小数点后3位),表示最终x的横、纵坐标。Sample Input
0 0 10 2 1
1 1 1
Sample Output
0.577 1.000分析
这是一道物理题,要求一个点p使得∑ni=1dist(pointi,pointp)∗wti最小,即广义上的带权费马点(woc,这是什么玩意儿)不会用物理方法,那就用另一些神奇的算法:爬山算法、模拟退火
代码
爬山算法
#include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define MAXN 10000 #define EPS 1e-5 using namespace std; int wt[MAXN+10],n; double x,y,ans; struct point{ double x,y; inline point(){ } inline point(double x,double y):x(x),y(y){ } inline point operator-(const point &b)const{ return point(x-b.x,y-b.y); } }a[MAXN+10]; void Read(int &x){ char c; bool f=0; while(c=getchar(),c!=EOF){ if(c=='-') f=1; if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); if(f) x=-x; return; } } } inline double sqr(double x){ return x*x; } inline double Get_dist(const point &a,const point &b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } inline double Get_dist(const point &p){ double ret(0); for(int i=1;i<=n;i++) ret+=Get_dist(p,a[i])*wt[i]; return ret; } void read(){ Read(n); int i,xx,yy; for(i=1;i<=n;i++){ Read(xx),Read(yy),Read(wt[i]); a[i]=point(xx,yy); x+=xx,y+=yy; } x/=n,y/=n; } double Get_rand(){ return 1.0*rand()/RAND_MAX; } void solve(){ ans=Get_dist(point(x,y)); double T=10000; while(T>EPS){ double dx=T*(Get_rand()*2-1),dy=T*(Get_rand()*2-1); double ret=Get_dist(point(x+dx,y+dy)); if(ret<ans) ans=ret,x+=dx,y+=dy; T*=0.98; } } int main() { read(); solve(); printf("%.3lf %.3lf\n",x,y); }
模拟退火
别用这份代码跑样例。。。。#include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define MAXN 10000 #define EPS 1e-9 using namespace std; int wt[MAXN+10],n; double x,y,ans; struct point{ double x,y; inline point(){ } inline point(double x,double y):x(x),y(y){ } inline point operator-(const point &b)const{ return point(x-b.x,y-b.y); } }a[MAXN+10]; void Read(int &x){ char c; bool f=0; while(c=getchar(),c!=EOF){ if(c=='-') f=1; if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); if(f) x=-x; return; } } } inline double sqr(double x){ return x*x; } inline double Get_dist(const point &a,const point &b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } inline double Get_dist(const point &p){ double ret(0); for(int i=1;i<=n;i++) ret+=Get_dist(p,a[i])*wt[i]; return ret; } void read(){ Read(n); int i,xx,yy; for(i=1;i<=n;i++){ Read(xx),Read(yy),Read(wt[i]); a[i]=point(xx,yy); x+=xx,y+=yy; } x/=n,y/=n; } double Get_rand(){ return 1.0*rand()/RAND_MAX; } void solve(){ ans=Get_dist(point(x,y)); double T=10000; while(T>EPS){ double dx=pow(T,2.0/3)*(Get_rand()*2-1),dy=pow(T,2.0/3)*(Get_rand()*2-1); double ret=Get_dist(point(x+dx,y+dy)); if(ret<ans) ans=ret,x+=dx,y+=dy; else{ double test=exp((ans-ret)/T); if(Get_rand()<test) ans=ret,x+=dx,y+=dy; } T*=0.99; } } int main() { read(); solve(); printf("%.3lf %.3lf\n",x,y); }
相关文章推荐
- [HihoCoder]#1040 : 矩形判断
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
- 毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
- 剑指offer---两个链表的第一个公共结点
- 从尾到头打印链表
- Windows下安装ZooKeeper
- thinkphp3.2【自动加载】
- (十)企业部分之cacti
- jQuery Ajax
- [HihoCoder]#1039 : 字符消除
- myschool简介
- JavaScript-----判断是否为手机浏览器访问
- 从泰勒公式到立方根的近似计算
- Android自定义控件(一):入门篇
- 光流法
- HDU 1213 How Many Tables
- 连续子数组的最大和
- [HihoCoder]#1049 : 后序遍历
- __name__的认识
- 发现D盘可用容量变小了