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

实际上就是一颗最小生成树,所谓的四维空间可以算出每一个点之间的距离,而且是无向图,可以用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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值