• [LibreOJ NOIP Round #1] 旅游路线


    [题目链接]

             https://loj.ac/problem/539

    [算法]

            首先 , 我们用f[u][k]表示现在在景点u ,还有k元钱 , 最多能够走多少路

            不难发现f[u][k] = max{ f[v][k - P[u]] + Dist(u,v,min(C,ci)) } ( dist(u,v,w)表示从u走到v , 最多经过w条路 , 最多能走多少路 )

            用倍增弗洛伊德求dist, 然后进行上述dp , 即可

            时间复杂度 : O(N^4 + N^3logN + TlogQ)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    const int inf = 1e9;
    #define MAXN 110
    #define MAXLOG 20
    
    int n,m,C,T,tot;
    int head[MAXN];
    int a[MAXN],b[MAXN],p[MAXN],c[MAXN];
    int dis[MAXN][MAXN],f[MAXN][MAXN * MAXN];
    int mat[MAXLOG][MAXN][MAXN];
    
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    
    int main() 
    {
            
            read(n); read(m); read(C); read(T);
            for (int i = 1; i <= n; i++)
            {
                    read(p[i]);
                    read(c[i]);
                    c[i] = min(c[i],C);
            }
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 1; j <= n; j++)
                    {
                            if (i != j)
                                    mat[0][i][j] = -inf;
                    }
            }
            for (int i = 1; i <= m; i++)
            {
                    int u,v,w;
                    read(u); read(v); read(w);
                    mat[0][u][v] = max(mat[0][u][v],w);
            }
            for (int i = 1; i < MAXLOG; i++)
            {
                    memcpy(mat[i],mat[i - 1],sizeof(mat[i]));
                    for (int k = 1; k <= n; k++)
                    {
                            for (int x = 1; x <= n; x++)
                            {
                                    for (int y = 1; y <= n; y++)
                                    {
                                            if (mat[i - 1][x][k] != -inf && mat[i - 1][k][y] != -inf)
                                                    mat[i][x][y] = max(mat[i][x][y],mat[i - 1][x][k] + mat[i - 1][k][y]);
                                    }
                            }
                    }
            }        
            for (int i = 1; i <= n; i++)
            {
                    for (int x = 1; x <= n; x++) a[x] = -inf;
                    a[i] = 0;
                    for (int k = 0; k < MAXLOG; k++)
                    {
                            if (c[i] & (1 << k))
                            {
                                    for (int x = 1; x <= n; x++) b[x] = -inf;
                                    for (int x = 1; x <= n; x++)
                                    {
                                            for (int y = 1; y <= n; y++)
                                            {
                                                    b[y] = max(b[y],a[x] + mat[k][x][y]);
                                            }
                                    }
                                    memcpy(a,b,sizeof(a));
                            }
                    }
                    for (int j = 1; j <= n; j++) dis[i][j] = a[j];
            }
            for (int i = 0; i <= n * n; i++)
            {    
                    for (int j = 1; j <= n; j++)
                    {
                            if (i < p[j])
                            {
                                    f[j][i] = 0;
                                    continue;
                            }
                            for (int k = 1; k <= n; k++) f[j][i] = max(f[j][i],f[k][i - p[j]] + dis[j][k]);
                    }
            }
            while (T--)
            {
                    int s,q,d;
                    read(s); read(q); read(d);
                    if (f[s][q] < d)
                    {
                            printf("-1
    ");
                            continue;
                    }
                    int l = 0 , r = q , mid , ans;
                    while (l <= r)
                    {
                            mid = (l + r) >> 1;
                            if (f[s][mid] >= d) 
                            {
                                    ans = mid;
                                    r = mid - 1;
                            } else l = mid + 1;
                    }
                    printf("%d
    ",q - ans);
            }
            
            return 0;
        
    }
  • 相关阅读:
    狗狗对主人的十句话
    微软提供正确卸载IE7的方法并恢复IE6
    c语言操作符的优先级
    linux 常用命令每日更新
    Visual Studio快捷键大全
    Opera将尽快发布补丁修复桌面浏览器漏洞 狼人:
    KILL杀毒软件重出江湖 公司股权全内资组成 狼人:
    图文:2010中国计算机网络安全年会华为展台 狼人:
    微软再次警告IE安全漏洞成为攻击目标 狼人:
    微软发布三月安全公告 两个补丁修补严重漏洞 狼人:
  • 原文地址:https://www.cnblogs.com/evenbao/p/9607906.html
Copyright © 2020-2023  润新知