幸福路径
【问题描述】
有向图G有n个顶点1, 2, …, n,点i的权值为w(i)。现在有一只蚂蚁,从给定的起点v0出发,沿着图G的边爬行。开始时,它的体力为1。每爬过一条边,它的体力都会下降为原来的ρ倍,其中ρ是一个给定的小于1的正常数。而蚂蚁爬到某个顶点时的幸福度,是它当时的体力与该点权值的乘积。 我们把蚂蚁在爬行路径上幸福度的总和记为H。很显然,对于不同的爬行路径,H的值也可能不同。小Z对H值的最大可能值很感兴趣,你能帮助他计算吗?注意,蚂蚁爬行的路径长度可能是无穷的。
【输入格式】
输入文件为path.in。文件的每一行中两个数之间用一个空格隔开。 输入文件第一行包含两个正整数n, m,分别表示G中顶点的个数和边的条数。 第二行包含n个非负实数,依次表示n个顶点权值w(1), w(2), …, w(n)。 第三行包含一个正整数v0,表示给定的起点。 第四行包含一个实数ρ,表示给定的小于1的正常数。 接下来m行,每行两个正整数x, y,表示<x, y>是G的一条有向边。可能有自环,但不会有重边。
【输出格式】
输出文件path.out仅包含一个实数,即H值的最大可能值,四舍五入到小数点后一位。
【样例输入】
5 5 10.0 8.0 8.0 8.0 15.0 1
0.5
1 2
2 3
3 4
4 2
4 5
【样例输出】
18.0
【样例说明】
当蚂蚁的爬行路径为1→2→3→4→2→3→4→…→2→3→4→…时,H = 10.0 +8.0*0.5+8.0*0.5^2+⋯。可以证明,这个无穷序列的总和为18.0,且这就是H的最大值。 另外,若本样例中w(5)改为17.0,其余数据不变,则当路径为1→2→3→4→5时,H = 18.0625。可以证明,这就是此时H的最大值。
【数据规模】
对于20%的数据,ρ ≤0.5; 另有20%的数据,保证H的最大值在有限路径上取到; 对于100%的数据,n ≤ 100,m ≤ 1000,ρ ≤ 1 – 10^-6,w(i) ≤ 100 (i = 1, 2, …, n)。
令f[i][j][t]为从点i走到点j花2^t步的最大幸福值,(不包括一开始站在i点的那个幸福值,这样不会在i->k->j中k转移处算重复,但是注意最后结果要加上begin点的幸福值)
那么有f[i][j][t]=max{f[i][k][t-1]+f[k][j][t-1]*p^(2^(t-1))},t要稍微大一点,最起码有25吧
迭代多次即可得到答案的近似值,用到的其实是倍增的思想。
注意蚂蚁可能卡死在某个点不动,因此初始要将邻接矩阵清为-INF,然后每个点连一条边为0的自环此外注意下卡死时最后经过的那个点的权值会不会被统计, 这里可能会挂。至于自环问题,一开始没想明白,加上就A了,否则WA一个点,不过后来想了想,我觉得可能是因为这个1->2->3->4线性图,找2^2时不存在4条路啊,只能是其中一个原地不动,凑够3条,所以原数组的定义可以修改为f[i][j][t]为从点i走到点j花不超过2^t步的最大幸福值。
1 #define ce freopen("path.in","r",stdin); 2 #define na freopen("path.ans","w",stdout); 3 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 8 int n,m,v,x,y; 9 double p,d[105]; 10 double f[105][105][50]; 11 double ans; 12 int main(){ 13 memset(f,-5,sizeof(f)); 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n;i++){ 16 scanf("%lf",&d[i]); 17 f[i][i][0]=0; 18 } 19 scanf("%d%lf",&v,&p); 20 for(int i=1;i<=m;i++){ 21 scanf("%d%d",&x,&y); 22 f[x][y][0]=d[y]*p; 23 } 24 for(int q=1;q<=35;q++){ 25 for(int k=1;k<=n;k++){ 26 for(int i=1;i<=n;i++){ 27 for(int j=1;j<=n;j++){ 28 if(f[i][j][q]<f[i][k][q-1]+f[k][j][q-1]*p) 29 f[i][j][q]=f[i][k][q-1]+f[k][j][q-1]*p; 30 if(i==v){ 31 if(f[i][j][q]>ans) ans=f[i][j][q]; 32 } 33 } 34 } 35 } 36 p*=p; 37 } 38 printf("%.1lf",ans+d[v]); 39 getchar(); getchar(); getchar(); 40 }