zoukankan      html  css  js  c++  java
  • BZOJ2306: [Ctsc2011]幸福路径

    Description

    有向图 G有n个顶点 1, 2, …, n,点i 的权值为 w(i)。现在有一只蚂蚁,从
    给定的起点 v0出发,沿着图 G 的边爬行。开始时,它的体力为 1。每爬过一条
    边,它的体力都会下降为原来的 ρ 倍,其中ρ 是一个给定的小于1的正常数。而
    蚂蚁爬到某个顶点时的幸福度,是它当时的体力与该点权值的乘积。
    我们把蚂蚁在爬行路径上幸福度的总和记为 H。很显然,对于不同的爬行路
    径,H 的值也可能不同。小 Z 对 H 值的最大可能值很感兴趣,你能帮助他计算
    吗?注意,蚂蚁爬行的路径长度可能是无穷的。

    Input

    每一行中两个数之间用一个空格隔开。
    输入文件第一行包含两个正整数 n, m,分别表示 G 中顶点的个数和边的条
    数。
    第二行包含 n个非负实数,依次表示 n个顶点权值 w(1), w(2), …, w(n)。
    第三行包含一个正整数 v0,表示给定的起点。
    第四行包含一个实数 ρ,表示给定的小于 1的正常数。
    接下来 m行,每行两个正整数 x, y,表示<x, y>是G的一条有向边。可能有
    自环,但不会有重边。

    Output

    仅包含一个实数,即 H值的最大可能值,四舍五入到小数点后一位。

    Sample Input

    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

    Sample Output

    18.0

    HINT

    对于 100%的数据, n ≤ 100, m ≤ 1000, ρ ≤ 1 – 10^-6

    , w(i) ≤ 100 (i = 1, 2, …, n)。

    Solution

    把点权换成边权,钦定每条边的边权为终点点权,那么答案就是边权最大和+起点点权。

    考虑这么一个转移方程

    [d^r[i][j]=d^{r-1}[i][k]+p^r*d^{r-1}[k][j] ]

    其中(d^r[i][j])表示路径i->j经过r条边的最大值。

    注意到p<1,所以当r足够大时,p无限趋近与0.所以随便选个大一点的r就好了...(根据题解,可选r=50)类似倍增floyd那样跑一下,然而因为r只需要取到50就够了所以直接枚举就好了不用倍增。

    这题还是没自己想出来啊,这个无限趋近于0根本没想到qwq。

    注意一个点就是(d^0[x][y]=p*val),因为已经经过一条边了。

    /**************************************************************
        Problem: 2306
        User: henryy
        Language: C++
        Result: Accepted
        Time:1656 ms
        Memory:6204 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    double a[110], f[52][110][110];
    int n, m, s;
     
    int main() {
        double ans = 0, p = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%lf", &a[i]);
        scanf("%d%lf", &s, &p);
        memset(f, -0x3f, sizeof(f));
        for(int k = 0; k <= 50; ++k) for(int i = 1; i <= n; ++i) f[k][i][i] = 0;
        for(int i = 1, x, y; i <= m; ++i) scanf("%d%d", &x, &y), f[0][x][y] = p * a[y];
        for(int t = 1; t <= 50; ++t, p *= p) {
            for(int k = 1; k <= n; ++k) for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) 
                f[t][i][j] = max(f[t][i][j], f[t-1][i][k] + p * f[t-1][k][j]);
        }
        for(int i = 1; i <= n; ++i) ans = max(ans, a[s] + f[50][s][i]);
        printf("%.1lf
    ", ans);
    }
    
  • 相关阅读:
    I-Cache和D-cache
    socat使用
    反射
    属性方法
    getitem
    文件打开编辑和函数参数
    python3编码问题个人理解
    正文内容 python3编码问题
    进度条制作
    集合关系
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10584831.html
Copyright © 2011-2022 走看看