实际上就是一颗最小生成树,所谓的四维空间可以算出每一个点之间的距离,而且是无向图,可以用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;
}