题目链接 LOJ
题解
考虑进行Dp,我们设
f[i][j]
f
[
i
]
[
j
]
表示到达节点
i
i
消耗了时间的开心度的期望,
状态转移的话直接对每一个节点枚举相邻的节点就可以,要提前处理出,从当前节点出发可以到达的节点的个数。
初始化的话
f[i][c[i]]
f
[
i
]
[
c
[
i
]
]
的值一定为
k[i]
k
[
i
]
,所以这样初始化就好,
对于节点
i
i
,要保证
j+c[edge[i].to]+edge[i].val<=k
j
+
c
[
e
d
g
e
[
i
]
.
t
o
]
+
e
d
g
e
[
i
]
.
v
a
l
<=
k
才可以,否则不会选
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
const int MAXN=1e6;
using namespace std;
int cnt,head[MAXN],k1[MAXN],k2[MAXN],c[MAXN],n,m,k;
double f[3000][3000],F[3000][3000];
struct Edge
{
int next,to,val;
}edge[MAXN];
inline void Add_Edge(int u,int v,int val)
{
edge[++cnt]=(Edge){head[u],v,val};
head[u]=cnt;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&k1[i],&k2[i]);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Add_Edge(x,y,z);
Add_Edge(y,x,z);
}
for(int j=k;j>=0;j--)
{
for(int i=1;i<=n;i++)
{
f[i][j]=k1[i],F[i][j]=k2[i];
int num=0;
for(int a=head[i];a;a=edge[a].next)
if(edge[a].val+j+c[edge[a].to]<=k) num++;
for(int a=head[i];a;a=edge[a].next)
{
if(edge[a].val+j+c[edge[a].to]<=k)
{
f[i][j]+=(f[edge[a].to][edge[a].val+j+c[edge[a].to]])/num;
F[i][j]+=(F[edge[a].to][edge[a].val+j+c[edge[a].to]])/num;
}
}
}
}
double sum1=0.0,sum2=0.0;
for(int i=1;i<=n;i++)
{
sum1+=f[i][c[i]]/n;
sum2+=F[i][c[i]]/n;
}
printf("%.5lf %.5lf",sum1,sum2);
return 0;
}