Consider Dick's back to be a plane with freckles at various (x,y) locations. Your job is to tell Richie how to connect the dots so as to minimize the amount of ink used. Richie connects the dots by drawing straight lines between pairs, possibly lifting the pen between lines. When Richie is done there must be a sequence of connected lines from any freckle to any other freckle.
The first line contains 0 < n ≤ 100, the number of freckles on Dick's back. For each freckle, a line follows; each following line contains two real numbers indicating the (x,y) coordinates of the freckle.
Your program prints a single real number to two decimal places: the minimum total length of ink lines that can connect all the freckles.
Sample Input
3 1.0 1.0 2.0 2.0 2.0 4.0
Output for Sample Input
3.41
Source: Waterloo Local Contest Sep. 23, 2000
最小生成树的模板,用prim算法最简单了吧。
#include <iostream> #include <iomanip> #include <algorithm> #include <math.h> using namespace std; const int INF=0x3f3f3f3f; int n,vn[105]; double lc[105],edge[105][105]; double prim(){ int i; for(i=0;i<n;i++){ vn[i] = 0; } for(i=0;i<n;i++){ lc[i] = INF; } int k = 0; vn[0] = -1;//根节点为0号节点,-1表示放入集合vn,非-1为在集合v-vn double ac = 0; for(i=0;i<n-1;i++){ double mc = INF; int mv = -1; for(int j=0;j<n;j++){ if(vn[j]!=-1){ double t = edge[j][k]; if(t<lc[j]){ lc[j] = t; vn[j] = k;//用点k的边更新vn中点到v-vn中各点的最短边 } if(lc[j]<mc){ mc = lc[j]; mv = j;//更新vn中点出发的最短边 } } } ac += mc; k = mv; vn[k] = -1; } return ac; } int main(){ int i,j,k; double x[105],y[105]; while(cin>>n){ for(i=0;i<n;i++){ cin>>x[i]>>y[i]; } for(i=0;i<n;i++){ for(j=0;j<n;j++){ edge[i][j]=edge[j][i]=sqrt( (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]) ); } } double ans = prim(); cout<<showpoint<<fixed <<setprecision(2)<<ans<<endl; } return 0; }
本文介绍了一种使用Prim算法解决最小生成树问题的方法,通过具体实例展示了如何在平面坐标系中找到连接多个点(模拟皮肤上的雀斑)的最短线路总长度。文章详细解释了Prim算法的实现过程,包括初始化、选择最小边和更新顶点状态等关键步骤,并提供了一段完整的C++代码示例。
216

被折叠的 条评论
为什么被折叠?



