首页 > 代码库 > poj1379+POJ2420+hdu3932(最短距离+费马点+模拟淬火算法)
poj1379+POJ2420+hdu3932(最短距离+费马点+模拟淬火算法)
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 5632 | Accepted: 1729 |
Description
Input
Output
Sample Input
31000 50 110 10100 100 410 1010 9090 1090 903000 3000 41200 8563 25002700 2650 2990 100
Sample Output
The safest point is (1000.0, 50.0).The safest point is (50.0, 50.0).The safest point is (1433.0, 1669.8).
Source
题解:
昨天在网上浏览博客,无意看见有个ACMer交了这题并注明模拟淬火算法,由于在人工智能课上老师提到过这类演化算法-模拟淬火算法。感慨ACM在线OJ还能用模拟淬火算法这类概率算法,于是眼前一亮,有登上好久没有刷题的POJ了,看了道题。
题意是要求到给定n个点的最小距离最大的点,且点限定在给定矩形内。要是一维的,直接三分找极值即可;在平面上就不太好处理了。且这样的点可能不只一个,到底取谁都要考虑。前人提供了模拟淬火算法,直接搞定了。大致步骤如下:
1、随机选取一个合适的控制条件T作为开始
2、随机选取P个起始点,作为可行解
3、分别依据内能更新这P个可行解
4、减小控制条件T,直到终止条件
下面是代码:
#include<iostream>#include<cmath>#include<ctime>#include<cstdio>using namespace std;const int MAXN=1000+100;const int KMEAN=30;const double INF=1<<30;const double eps=1e-8;const double PI=3.141592653;int x,y,n;struct Point{ double x,y;}myPoint[MAXN],myK[KMEAN];double dis[KMEAN];double GetMinDis(double tx,double ty){ double minDis=INF,temp; for(int i=0;i<n;i++) { temp=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y)); if(temp<minDis) minDis=temp; } return minDis;}int main(){ int cas,i,j; double temp; scanf("%d",&cas); while(cas--) { scanf("%d%d%d",&x,&y,&n); srand((unsigned)time(NULL)); for(i=0;i<n;i++) scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y); for(i=0;i<KMEAN;i++) { dis[i]=INF; myK[i].x=rand()%10001/10000.0*x; myK[i].y=rand()%10001/10000.0*y; } for(i=0;i<KMEAN;i++) dis[i]=GetMinDis(myK[i].x,myK[i].y); double theta,delta=1.0*(x>y?x:y)/sqrt(1.0*n); while(delta>eps) { for(i=0;i<KMEAN;i++) { double nx=myK[i].x,ny=myK[i].y; for(j=0;j<KMEAN;j++) { double tx,ty; theta=double(rand()%10001)/10000.0*2*PI; tx=nx+delta*cos(theta); ty=ny+delta*sin(theta); if(tx<0||tx>x||ty<0||ty>y) continue; temp=GetMinDis(tx,ty); if(temp>dis[i]) { myK[i].x=tx; myK[i].y=ty; dis[i]=temp; } } } delta=0.8*delta; } int id=-1; temp=-INF; for(i=0;i<KMEAN;i++) { if(dis[i]>temp) { temp=dis[i]; id=i; } } printf("The safest point is (%.1lf, %.1lf).\n",myK[id].x,myK[id].y); } return 0;}
下面是相似的题
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3274 | Accepted: 1666 |
Description
Unfortunately, Luke cannot use his existing cabling. The 100mbs system uses 100baseT (twisted pair) cables. Each 100baseT cable connects only two devices: either two network cards or a network card and a hub. (A hub is an electronic device that interconnects several cables.) Luke has a choice: He can buy 2N-2 network cards and connect his N computers together by inserting one or more cards into each computer and connecting them all together. Or he can buy N network cards and a hub and connect each of his N computers to the hub. The first approach would require that Luke configure his operating system to forward network traffic. However, with the installation of Winux 2007.2, Luke discovered that network forwarding no longer worked. He couldn‘t figure out how to re-enable forwarding, and he had never heard of Prim or Kruskal, so he settled on the second approach: N network cards and a hub.
Luke lives in a loft and so is prepared to run the cables and place the hub anywhere. But he won‘t move his computers. He wants to minimize the total length of cable he must buy.
Input
Output
Sample Input
40 00 1000010000 1000010000 0
Sample Output
28284
题解:
本题与上面那题的唯一区别就是目的函数不同,此处为最短距离和,上面为最短距离的最大者,模拟淬火算法。直接贴代码的。
#include<iostream>#include<cmath>#include<ctime>#include<cstdio>using namespace std;const int MAXN=100+10;const int KMEAN=30;const double INF=1<<30;const double eps=1e-8;const double PI=3.141592653;double x=10000.0,y=10000.0;int n;struct Point{ double x,y;}myPoint[MAXN],myK[KMEAN];double dis[KMEAN];double GetMinDis(double tx,double ty){ double temp=0; for(int i=0;i<n;i++) { temp+=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y)); } return temp;}int main(){ int i,j; double temp; while(scanf("%d",&n)!=EOF) { srand((unsigned)time(NULL)); for(i=0;i<n;i++) scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y); for(i=0;i<KMEAN;i++) { dis[i]=INF; myK[i].x=rand()%10001/10000.0*x; myK[i].y=rand()%10001/10000.0*y; } for(i=0;i<KMEAN;i++) dis[i]=GetMinDis(myK[i].x,myK[i].y); double theta,delta=10000.0/sqrt(1.0*n); while(delta>eps) { for(i=0;i<KMEAN;i++) { double nx=myK[i].x,ny=myK[i].y; for(j=0;j<KMEAN;j++) { double tx,ty; theta=double(rand()%10001)/10000.0*2*PI; tx=nx+delta*cos(theta);//可改变方向 ty=ny+delta*sin(theta); temp=GetMinDis(tx,ty); if(temp<dis[i]) { myK[i].x=tx; myK[i].y=ty; dis[i]=temp; } } } delta=0.98*delta; } temp=INF; for(i=0;i<KMEAN;i++) { if(dis[i]<temp) { temp=dis[i]; } } printf("%.0lf\n",temp); } return 0;}
下面这题是求最小圆覆盖。
Groundhog Build Home
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1397 Accepted Submission(s): 625
1000 50 110 101000 50 40 01 00 11 1
(10.0,10.0).0.0(0.5,0.5).0.7
题解:
题意是要求到给定n个点的最大距离最小的点,且点限定在给定矩形内,对应数学模型最小点覆盖。贴段代码:
#include<iostream>#include<cmath>#include<ctime>#include<cstdio>using namespace std;const int MAXN=1000+100;const int KMEAN=30;const double INF=1<<30;const double eps=1e-8;const double PI=3.141592653;int x,y,n;struct Point{ double x,y;}myPoint[MAXN],myK[KMEAN];double dis[KMEAN];double GetMaxDis(double tx,double ty){ double maxDis=-INF,temp; for(int i=0;i<n;i++) { temp=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y)); if(temp>maxDis) maxDis=temp; } return maxDis;}int main(){ int i,j; double temp; while(scanf("%d%d%d",&x,&y,&n)!=EOF) { srand((unsigned)time(NULL)); for(i=0;i<n;i++) scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y); for(i=0;i<KMEAN;i++) { dis[i]=INF; myK[i].x=rand()%10001/10000.0*x; myK[i].y=rand()%10001/10000.0*y; } for(i=0;i<KMEAN;i++) dis[i]=GetMaxDis(myK[i].x,myK[i].y); double theta,delta=1.0*(x>y?x:y)/sqrt(1.0*n); while(delta>eps) { for(i=0;i<KMEAN;i++) { double nx=myK[i].x,ny=myK[i].y; for(j=0;j<KMEAN;j++) { double tx,ty; theta=double(rand()%10001)/10000.0*2*PI; tx=nx+delta*cos(theta); ty=ny+delta*sin(theta); if(tx<0||tx>x||ty<0||ty>y) continue; temp=GetMaxDis(tx,ty); if(temp<dis[i]) { myK[i].x=tx; myK[i].y=ty; dis[i]=temp; } } } delta=0.8*delta; } int id=-1; temp=INF; for(i=0;i<KMEAN;i++) { if(dis[i]<temp) { temp=dis[i]; id=i; } } printf("(%.1lf,%.1lf).\n%.1lf\n",myK[id].x,myK[id].y,temp); } return 0;}