自己用SPFA做,T了。刚开始还不相信,N<=50,(井底之蛙的集中体现).看了大牛博客看了很久,我做题思路基本上是剽窃的。
大牛博客链接 http://blog.csdn.net/L123012013048/article/details/47820453
这道题主要是要处理负环,但这个负环很特殊,跑着跑着负环就没了。
eg. 本来的负环的某个虫洞的到达时间小于虫洞的生成时间,那么负环就消失了
我之前为什么用spfa超时,就是有可能存在这种负环且消失时间很久,比如每跑一次负环时间-1,但负环中的虫洞的生成时间最晚是-99999(一个很小的数就对了),如果现在时间是0,那要跑这个负环接近99999次负环才会消失。
但是,其实可以发现负环的时候就把他消灭掉。因为负环内的点满足的最优情况就是某个点到达时间刚好等于生成时间(其他点<=)
这样就可以求出这个负环内的能节省的最多时间,然后将所有点都减去那个时间,那么负环就消失了
/*
把开始点和结束点看作穿越时间为0,建的时间是-INF的虫洞
每次计算dis[i][j]表示从i虫洞的出口到j虫洞入口的距离
(这道题距离可以说就是时间)
d[i]表示开始点虫洞的入口到i虫洞的出口的时间
max(dt[i]+dis[i][j],wom[j].t)+wom[j].d就是当前i虫洞的出口转移到j虫洞的出口的时间。(注意:如果j虫洞还没建成,可以等它建成)
找出更新的值,破除这个负环,更新的值就是到达起点的值和生成时间的差的最小值,因为在负环内可以等待到生成时间(太渣,没能想到这一点)
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
#define mpow(X) ((X)*(X))
typedef long long LL;
using namespace std;
const int MAXN=60;
const int INF=0x3f3f3f3f;
struct _Point
{
int x,y,z;
};
struct _Wom
{
struct _Point in,ot;
int t,d;
}wom[MAXN];
int dis[MAXN][MAXN];
int dt[MAXN],pre[MAXN];
inline int dist(int u,int v)
{return ceil(sqrt((double)(mpow(wom[u].ot.x-wom[v].in.x)+
mpow(wom[u].ot.y-wom[v].in.y)+mpow(wom[u].ot.z-wom[v].in.z))));}
void Bellman(int beg,int n)
{
for(int i=0;i<=n;i++) dt[i]=INF;
dt[beg]=0;
msc(pre);
while(1){
bool flg=false;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
{
int nt=max(dt[i]+dis[i][j],wom[j].t)+wom[j].d;
if(dt[j]>nt)
dt[j]=nt,pre[j]=i,flg=true;
}
if(!flg) {printf("%d\n",dt[n] );return;}
for(int i=0;i<=n;i++)
{
int k=i;
for(int j=0;k!=-1&&j<=n;j++) k=pre[k];
if(k==-1) continue;
int Mic=dt[pre[k]]+dis[pre[k]][k]-wom[k].t;
for(int p=pre[k];p!=k;p=pre[p])
Mic=min(Mic,dt[pre[p]]+dis[pre[p]][p]-wom[p].t);
if(Mic<=0) continue;
dt[k]-=Mic;
for(int p=pre[k];p!=k;p=pre[p])
dt[p]-=Mic;
}
}
}
int main(int argc, char const *argv[])
{
int c;
cin>>c;
while(c--){
int n;
struct _Point tmp;
scanf("%d %d %d",&tmp.x,&tmp.y,&tmp.z);
wom[0].in=wom[0].ot=tmp,wom[0].t=-INF,wom[0].d=0;
scanf("%d %d %d%d",&tmp.x,&tmp.y,&tmp.z,&n);
n++;
wom[n].in=wom[n].ot=tmp,wom[n].t=-INF,wom[n].d=0;
for(int i=1;i<n;i++)
{
scanf("%d %d %d",&tmp.x,&tmp.y,&tmp.z);
wom[i].in=tmp;
scanf("%d %d %d",&tmp.x,&tmp.y,&tmp.z);
wom[i].ot=tmp;
scanf("%d %d",&wom[i].t,&wom[i].d);
}
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dis[i][j]=dist(i,j);
Bellman(0,n);
}
return 0;
}
/*
2
0 0 0 100 0 0
2
1 1 0 1 2 0 -100 -2
0 1 0 100 1 0 -150 10
0 0 0 10 0 0
1
5 0 0 -5 0 0 0 0
*/