题目
计算从哪里开始点火,使得燃烧的总时间最短,输出最短时间。
分析
把木棍分成两小段
floyd求出被燃烧的最短时间
再求出答案
floyd代码
#include <cstdio>
#include <climits>
#include <cctype>
#define eij e[i][j]!=INT_MAX
#define dxi d[x][i]!=INT_MAX
using namespace std;
struct node{int x1,y1,x2,y2,t;}f[41];
struct nobe{int xx,yy;}v[83];
int n,m,e[83][83],d[83][83]; double ans=INT_MAX,cc;
int in(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)&&c!='-') c=getchar();
if (c=='-') c=getchar(),f=-f;
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
double min(double a,double b){return (a<b)?a:b;}
double max(double a,double b){return (a>b)?a:b;}
int gett(int x,int y){
for (int i=1;i<=m;i++) if (v[i].xx==x&&v[i].yy==y) return i;//找到返回
v[++m].xx=x; v[m].yy=y;
for (int i=1;i<m;i++) e[i][m]=e[m][i]=INT_MAX;//初始化
e[m][m]=0; return m;
}
void add(int x1,int y1,int x2,int y2,int t){
int i=gett(x1,y1),j=gett(x2,y2);
e[i][j]=e[j][i]=t;
}
double anw(int x){
double kk=0,ss;
for (int i=1;i<=m;i++)
if (dxi) kk=max(kk,d[x][i]);
for (int i=1;i<m;i++)
for (int j=i+1;j<=m;j++)
if (eij&&d[x][i]<d[x][j]+e[i][j]&&d[x][j]<d[x][i]+d[i][j]){//是否相连
if (d[x][i]<d[x][j]) ss=d[x][j]+(e[i][j]-(d[x][j]-d[x][i]))/2.0;//计算出烧完的时间
else ss=d[x][i]+(e[i][j]-(d[x][i]-d[x][j]))/2.0;//计算出烧完的时间
kk=max(kk,ss);//求最大值
}
return kk;
}
void init();
int main(){
freopen("fire.in","r",stdin);
freopen("fire.out","w",stdout);
init();//初始化
for (int k=1;k<=m;k++)
for (int i=1;i<=m;i++)
for (int j=1;j<=m;j++)
if (d[i][j]>(long long)d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];//floyd
for (int i=1;i<=m;i++)
if (!(v[i].xx%2)&&!(v[i].yy%2)) //在两头cc=anw(i),ans=min(ans,cc);
printf("%.4lf",ans/2.0); return 0;
}
void init(){
n=in(); for (int i=1;i<=n;i++)
f[i].x1=in(),f[i].y1=in(),f[i].x2=in(),f[i].y2=in(),f[i].t=in();
for (int i=1;i<=n;i++) add(f[i].x1*2,f[i].y1*2,f[i].x1+f[i].x2,f[i].y1+f[i].y2,f[i].t),add(f[i].x1+f[i].x2,f[i].y1+f[i].y2,f[i].x2*2,f[i].y2*2,f[i].t);//截成两小段
for (int i=0;i<=m+1;i++) for (int j=0;j<=m+1;j++) d[i][j]=e[i][j];
}