poj 2728 最优比率树(最小生成树问题)
好蛋疼啊,由于double 不能用memset,害的我调了一个多小时才发现。由于用二分搜索,时间有点大
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #define maxn 1005 using namespace std; const int INF = 0x3f3f3f; struct node{ int x,y,z; }Node[maxn]; double d[maxn]; double G[maxn][maxn]; double cost[maxn][maxn]; double benefit[maxn][maxn]; int n; double mid,ans; void calculate(int i,int j){ cost[i][j] = cost[j][i] = abs(Node[i].z - Node[j].z); int x1=Node[i].x, y1=Node[i].y; int x2=Node[j].x, y2=Node[j].y; benefit[i][j] = benefit[j][i] = sqrt(1.0*(x1-x2)*(x1-x2) + 1.0*(y1-y2)*(y1-y2)); } void makemap(){ for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ G[i][j] = G[j][i] = cost[i][j] - mid * benefit[i][j]; } return; } void prim(){ bool vis[maxn]; double mindist; double lowdist[maxn]; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) lowdist[i] = INF; int point; ans = 0.0; int s=1; int num=1; while(true){ if(num == n) break; vis[s] = true; mindist = INF; for(int i=1;i<=n;i++){ if(!vis[i] && lowdist[i] > G[s][i]){ lowdist[i] = G[s][i]; } if(!vis[i] && lowdist[i] < mindist){ mindist = lowdist[i]; point = i; } } s = point; ans += mindist; num++; } return; } int main() { //if(freopen("input.txt","r",stdin)== NULL) {printf("Error\n"); exit(0);} while(cin>>n && n){ for(int i=1;i<=n;i++){ cin>>Node[i].x>>Node[i].y>>Node[i].z; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ calculate(i,j); } double R=10000000,L=0.0; while( (R-L)>1e-6 ){ mid = (R+L)/2; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ G[i][j] = INF; } makemap(); prim(); if(ans >= 0) L = mid; else R = mid; } printf("%.3lf\n",L); } return 0; }
还是迭代好上面的用时2500多MS,而这个只要297MS,空间复杂度是降不下来了。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #define maxn 1005 using namespace std; const int INF = 0x3f3f3f; struct node{ int x,y,z; }Node[maxn]; double d[maxn]; double G[maxn][maxn]; double cost[maxn][maxn]; double benefit[maxn][maxn]; int n; double mid,ans; void calculate(int i,int j){ cost[i][j] = cost[j][i] = abs(Node[i].z - Node[j].z); int x1=Node[i].x, y1=Node[i].y; int x2=Node[j].x, y2=Node[j].y; benefit[i][j] = benefit[j][i] = sqrt(1.0*(x1-x2)*(x1-x2) + 1.0*(y1-y2)*(y1-y2)); } void makemap(){ for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ G[i][j] = G[j][i] = cost[i][j] - mid * benefit[i][j]; } return; } void prim(){ bool vis[maxn]; double mindist; struct low{ double lowdist; int s; }L[maxn]; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) L[i].lowdist = INF; int point; ans = 0.0; int s=1; int num=1; double suma = 0.0,sumb = 0.0; while(true){ if(num == n) break; vis[s] = true; mindist = INF; for(int i=1;i<=n;i++){ if(!vis[i] && L[i].lowdist > G[s][i]){ L[i].lowdist = G[s][i]; L[i].s = s; } if(!vis[i] && L[i].lowdist < mindist){ mindist = L[i].lowdist; point = i; } } int a = L[point].s; suma += cost[a][point]; sumb += benefit[a][point]; s = point; num++; } ans = suma/sumb; return; } int main() { //if(freopen("input.txt","r",stdin)== NULL) {printf("Error\n"); exit(0);} while(cin>>n && n){ for(int i=1;i<=n;i++){ cin>>Node[i].x>>Node[i].y>>Node[i].z; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++){ calculate(i,j); } mid = 0.5; while( true){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ G[i][j] = INF; } makemap(); prim(); if(abs(ans -mid) < 1e-6) break; else mid = ans; } printf("%.3lf\n",ans); } return 0; }