题目大意
题目说的相当清楚了,不解释,点传送门。
解题分析
这道题就是利用期望的线性的性质来做。所以想到DP,但是正推会有点难,可以想到从x相邻的节点走到x的概率是不同的,但是从x走到相邻的节点概率是相同的,所以可以考虑逆向处理
f[i][j][0/1]:现在走到第i个景点,从j时刻开始走(配合倒推……),(小y/他的妹子)的开心度的期望值
则转移方程为(推的时候把0/1这一维省略掉,反正不会串)
f[i][j]+=f[son[j]][j+c[son[j]]+w[j]]/num,其中num为可以在时限内游玩完成且相邻的所有景点个数
#include<cstdio>
#include<cstring>
#define maxn 105
#define maxe 20005
#define maxv 60005
using namespace std;
int n,e,k,tot,son[maxe],nxt[maxe],w[maxe],lnk[maxn],c[maxn],a[maxn],b[maxn];
double ansx,ansy,f[105][505][2];
inline void readi(int &x){
x=0; char ch=getchar();
while ('0'>ch||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
}
void _add(int x,int y,int z){
tot++; son[tot]=y; w[tot]=z; nxt[tot]=lnk[x]; lnk[x]=tot;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
readi(n); readi(e); readi(k); tot=0; ansx=ansy=0.0;
for (int i=1;i<=n;i++) {readi(c[i]); readi(a[i]); readi(b[i]);}
for (int i=1,x,y,z;i<=e;i++){
readi(x); readi(y); readi(z); _add(x,y,z); _add(y,x,z);
}
for (int ti=k;ti;ti--)
for (int i=1,tem;i<=n;i++){
tem=0; f[i][ti][0]=a[i]; f[i][ti][1]=b[i];
for (int j=lnk[i];j;j=nxt[j]) tem+=(ti+w[j]+c[son[j]]<=k);
for (int j=lnk[i];j;j=nxt[j]) if (ti+w[j]+c[son[j]]<=k)
{f[i][ti][0]+=f[son[j]][ti+w[j]+c[son[j]]][0]/tem; f[i][ti][1]+=f[son[j]][ti+w[j]+c[son[j]]][1]/tem;}
}
for (int i=1;i<=n;i++) {ansx+=f[i][c[i]][0]/n; ansy+=f[i][c[i]][1]/n;}
printf("%.5lf %.5lf",ansx,ansy);
return 0;
}