CodeVs 3315 时空跳跃者的魔法(最终版本)

来源:互联网 发布:mac能装盗版软件吗 编辑:程序博客网 时间:2024/04/29 23:39

实际上就是一颗最小生成树,所谓的四维空间可以算出每一个点之间的距离,而且是无向图,可以用Prim算法来实现。

Prim:

      1.O(n^2)

        
#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#include<cstring>#include<string>using namespace std;typedef long long ll;const long long  INF=0xffffff;const int M=1005;int n;ll h;ll hh;struct zb{ll x, y, z, t;};zb s[M];ll cost[M];int vis[M];ll map[M][M];void prim(){    for (ll i=1; i<=n; i++)    {    ll ss;    ll minn=INF;    for (ll j=1; j<=n; j++)    {    if (!vis[j] && cost[j]<minn)    {    minn=cost[j];    ss=j;    }    }    vis[ss]=1;    hh+=minn;    for (ll j=1; j<=n; j++)    {    if (!vis[j] && map[ss][j]<cost[j] && map[ss][j]>0) cost[j]=map[ss][j];    }        }}void init(){memset(map, 127, sizeof(map));memset(s, 0, sizeof(s));scanf("%d", &n);for (int i=1; i<=n; i++) scanf("%d %d %d %d", &s[i].x, &s[i].y,  &s[i].z,  &s[i].t);scanf( "%dTas", &h);for (int i=1; i<=n; i++)  for (int j=1; j<=n; j++)  {  if (i!=j)  {    map[i][j]=map[j][i]=floor(sqrt((s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y)+(s[i].z-s[j].z)*(s[i].z-s[j].z))+abs(s[i].t-s[j].t));    }  }for (ll i=1; i<=n; i++){cost[i]=INF;vis[i]=false;}cost[1]=0;}int main(){init();prim();if (hh>h) printf("Death\n");else printf("%dTas", hh);return 0;}




          2.O(n log2 n)

#include<cstdio>#include<cstdlib>#include<cmath>#include<vector>#include<functional>#include<queue>#include<algorithm>#include<cstring>#include<string>using namespace std;FILE *fin = fopen ("magic.in","r");FILE *fout = fopen("magic.out", "w");typedef long long ll;typedef pair <ll, int>P;const long long  INF=0xffffff;const int M=1005;int n;ll h;ll hh;struct zb{ll x, y, z, t;};zb s[M];ll cost[M];int vis[M];ll map[M][M];void prim(){priority_queue<P, vector<P>, greater<P> >que;que.push(P(0,1));while (!que.empty()){P s=que.top();que.pop();int v=s.second;if (cost[v]<s.first) continue;hh+=s.first;vis[v]=1;for (int i=1; i<=n; i++){if (!vis[i] && cost[i]>map[v][i] && map[v][i]>0){cost[i]=map[v][i];que.push(P(cost[i], i));}}}}void init(){memset(map, 127, sizeof(map));memset(s, 0, sizeof(s));fscanf(fin, "%d", &n);for (int i=1; i<=n; i++) fscanf(fin, "%d %d %d %d", &s[i].x, &s[i].y,  &s[i].z,  &s[i].t);fscanf(fin, "%dTas", &h);for (int i=1; i<=n; i++)  for (int j=1; j<=n; j++)  {  if (i!=j)  {    map[i][j]=map[j][i]=floor(sqrt((s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y)+(s[i].z-s[j].z)*(s[i].z-s[j].z))+abs(s[i].t-s[j].t));    }  }for (ll i=1; i<=n; i++){cost[i]=INF;vis[i]=false;}cost[1]=0;}int main(){init();prim();if (hh>h) fprintf(fout, "Death\n");else fprintf(fout, "%dTas", hh);return 0;}



kruskal:

*需要注意的地方:kruskal我就不多讲了,讲一讲程序的地方。若点数为n,储存空间必须开到n*(n-1)/2约等于o(n^2),我一直卡在这里大半天了,感谢cmb老师给的提醒。
#include<cstdlib>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int M=1000005; typedef long long ll;const ll INF=0xffffff;struct Edge{int s;int t;ll val;};Edge s[M];  。 ll x[M];ll y[M];ll z[M];ll t[M];ll n,h, hh;int f[M];ll side;     int bfind(int x){if (f[x]==x) return x;f[x]=bfind(f[x]);return f[x];}void bunion(int x, int y){int x1=bfind(x);int y1=bfind(y);f[x1]=y1;}bool cmp(Edge a, Edge b){return a.val<b.val;}void kruskal(){int i=1;int j=0;int v1, v2;sort(s+1, s+side+1, cmp);while (i<side){v1=bfind(s[i].s);v2=bfind(s[i].t);if (v1!=v2){bunion(v1, v2);hh+=s[i].val;if (++j==n-1) break;//printf("%d", hh);}i++;}}void init(){side=0;scanf ("%d", &n);for (int i=1; i<=n; i++) scanf("%d %d %d %d", &x[i], &y[i], &z[i], &t[i]);scanf("%dTas", &h);for (int i=1; i<=n; i++)  for (int j=1; j<=n; j++){  if (i!=j)  {  s[++side].s=i;  s[side].t=j;  s[side].val=floor(sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j])))+abs(t[i]-t[j]);  }  }  for (int i=1; i<=n; i++) f[i]=i;}int main(){init();kruskal();if (hh<=h) printf("%dTas", hh);else printf("Death");return 0;}


0 0
原创粉丝点击