幸福路径

题目大意:

给定一个有向图,每一个点都有一个点权,给出起点,每一次移动体力值都会减小为原来的p倍,得到的权值就是当时的体力和该点点权之积,求最大的权值之和。

对于这道题,我们可以这样想:由于我们不断的往下走,每一次相对之前增加量就会越来越小,那么我们走很远很远的路径之后,我们就可以看作达到最大值了(也就是远小于精度之后)。

我们定义f[i][j][k]代表从i到j的最大幸福度,而k代表的是迭代的次数,那么当k到达一定的大小的时候,我们就可以认为是答案了

那么我们如何进行迭代呢?我们首先设定起始状态,就是每一个边的到达点的点权乘以p,然后我们逐步减小p,每一次都利用flyod的思想,枚举中间接口,动态转移方程就是f[i][j][cnt]=max(f[i][j][cnt],f[i][k][cnt-1]+f[k][j][cnt-1]*p)

而关于记录答案,我们只要当i等于起点时,和当时的ans取一个max就行了。。。

注意处理细节,给每一个点连一个f[i][i][0]=0,因为题目中说有自环。

最后,附上本题代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 using namespace std;
 6 //Debug Yufenglin
 7 #define dej printf("Running
");
 8 #define dep1(x) cout<<#x<<"="<<x<<endl;
 9 #define dep2(x,y) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<endl;
10 #define dep3(x,y,z) cout<<#x<<"="<<x<<' '<<#y<<"="<<y<<' '<<#z<<"="<<z<<endl;
11 
12 //Standfor Yufenglin
13 #define LL long long
14 #define LB long double
15 #define reg register
16 #define il inline
17 #define inf 1e8
18 #define maxn 100
19 #define maxm 40
20 
21 int n,m,v;
22 LB ans,f[maxn+5][maxn+5][maxm],w[maxn+5];
23 LB p;
24 
25 int main()
26 {
27     memset(f,-0x1f,sizeof(f));
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++)
30     {
31         scanf("%Lf",&w[i]);
32         f[i][i][0]=0;
33     }
34     scanf("%d%Lf",&v,&p);
35     for(int i=1;i<=m;i++)
36     {
37         int x,y;
38         scanf("%d%d",&x,&y);
39         f[x][y][0]=p*w[y];
40     }
41     for(int cnt=1;cnt<=25;cnt++)
42     {
43         for(int k=1;k<=n;k++)
44         {
45             for(int i=1;i<=n;i++)
46             {
47                 for(int j=1;j<=n;j++)
48                 {
49                     f[i][j][cnt]=max(f[i][j][cnt],f[i][k][cnt-1]+f[k][j][cnt-1]*p);
50                     if(i==v) ans=max(ans,f[i][j][cnt]);
51                 }
52             }
53         }
54         p*=p;
55     }
56     printf("%.1Lf
",w[v]+ans);
57     return 0;
58 }
原文地址:https://www.cnblogs.com/yufenglin/p/10688911.html