题目链接:https://vjudge.net/problem/POJ-2728
题目意思:给你n个村庄的坐标和每个村庄的海拔。建设管道需要花费(为两村庄高度差)。现在求 总花费/总距离(各条线路的距离)的最小值。
思路:https://www.jianshu.com/p/d40a740a527e
入门级别,0/1规划,最优入门题。用链式前向星、Dis数组放外面会T成SB
二分法:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<iomanip> 5 #include<algorithm> 6 #include<string.h> 7 #define eqs 1e-6; 8 using namespace std; 9 const int MAXN = 1010; 10 const int INF = 999999; 11 double Graph[MAXN][MAXN]; 12 struct P{ 13 double x,y,z; 14 }Cy[MAXN]; 15 int N; 16 double distance(double x1,double y1,double x2,double y2){ 17 double ret=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 18 return sqrt(ret); 19 } 20 void UpdateMap(double l){ 21 for(int i = 1;i <= N;i ++){ 22 for(int j = 1;j <= N;j ++){ 23 Graph[i][j] = fabs(Cy[i].z - Cy[j].z) - l * distance(Cy[i].x,Cy[i].y,Cy[j].x,Cy[j].y); 24 } 25 } 26 } 27 double dis[MAXN]; 28 double prim(){ 29 double minn; 30 double sum = 0; 31 bool vis[MAXN]; 32 int now; 33 memset(vis,0,sizeof(vis)); 34 for(int i = 1;i <= N;i ++){ 35 dis[i] = Graph[1][i]; 36 } 37 vis[1] = 1; 38 for(int i = 1;i <= N;i ++){ 39 minn = INF; 40 for(int j = 1;j <= N;j++){ 41 if(!vis[j]){ 42 if(dis[j] < minn){ 43 now = j; 44 minn = dis[j]; 45 } 46 } 47 } 48 if(minn == INF) break; 49 sum += minn; 50 vis[now] = 1;//cout<<"i = "<<i<<endl; 51 for(int j = 1;j <= N;j ++){ 52 if(!vis[j] && dis[j] >= Graph[now][j]) 53 dis[j] = Graph[now][j]; 54 } 55 } 56 return sum; 57 } 58 int main(){ 59 while(cin>>N,N){ 60 for(int i = 1;i <= N;i ++){ 61 cin>>Cy[i].x>>Cy[i].y>>Cy[i].z; 62 } 63 double high = 100.0; 64 double low = 0.0 , pre = 0.0; 65 double mid,ans; 66 while(low <= high){ 67 mid = (high + low)/2; 68 UpdateMap(mid); 69 ans = prim(); 70 if(fabs(pre - ans) <= 0.0005) break; 71 if(ans > 0.0005) low = mid; 72 else high = mid; 73 } 74 // cout<<fixed<<setprecision(3)<<mid<<endl; 75 printf("%.3lf ",mid); 76 } 77 return 0; 78 }
迭代法:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string.h> 5 #include<algorithm> 6 #include<iomanip> 7 using namespace std; 8 const int N = 1010; 9 const int INF = 999999; 10 struct P{ 11 double x,y,z; 12 }num[N]; 13 int n; 14 double mp[N][N],cost[N][N],len[N][N]; 15 double cal(double x1,double y1,double x2,double y2){ 16 return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); 17 } 18 double dis[N]; 19 bool vis[N]; 20 int now , pre[N]; 21 double prim(){ 22 double sum = 0; 23 double sumlen = 0,sumcost = 0; 24 for(int i = 1;i <= n;i ++){ 25 dis[i] = mp[1][i]; 26 vis[i] = false; 27 pre[i] = 1; 28 } 29 vis[1] = true; 30 for(int i = 1;i <= n;i ++){ 31 double minn = INF; 32 for(int j = 1;j <= n ;j ++){ 33 if(!vis[j]){ 34 if(dis[j] < minn){ 35 minn = dis[j]; 36 now = j; 37 } 38 } 39 } 40 if(minn == (double)INF) break; 41 sumlen += len[pre[now]][now]; 42 sumcost += cost[pre[now]][now]; 43 // cout<<"now = "<<now<<endl; 44 vis[now] = true; 45 for(int j = 1;j <= n;j ++){ 46 if(!vis[j] && dis[j] > mp[now][j]){ 47 dis[j] = mp[now][j]; 48 pre[j] = now; 49 } 50 } 51 } 52 return sumcost/sumlen; 53 } 54 int main(){ 55 while(cin>>n,n){ 56 for(int i = 1;i <= n;i ++){ 57 cin>>num[i].x>>num[i].y>>num[i].z; 58 } 59 for(int i = 1;i <= n;i ++){ 60 for(int j = i + 1;j <= n;j ++){ 61 cost[j][i] = cost[i][j] = fabs(num[i].z - num[j].z); 62 len[i][j] = len[j][i] = cal(num[i].x,num[i].y,num[j].x,num[j].y); 63 } 64 } 65 double sumlen = 0,sumcost = 0; 66 for(int i = 2;i <= n;i ++){ 67 sumlen += len[1][i]; 68 sumcost += cost[1][i]; 69 } 70 double x; 71 double ans = sumcost/sumlen; 72 while(1){ 73 x = ans; 74 for(int i = 1;i <= n;i ++){ 75 for(int j = i + 1;j <= n;j ++){ 76 mp[j][i] = mp[i][j] = fabs(num[i].z - num[j].z) - x * cal(num[i].x,num[i].y,num[j].x,num[j].y); 77 } 78 } 79 ans = prim(); 80 if(fabs(ans - x) <= 0.0005) break; 81 } 82 cout<<fixed<<setprecision(3)<<ans<<endl; 83 } 84 return 0; 85 }