[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\n");
                        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\n",q - ans);
        }
        
        return 0;
    
}

 

posted @ 2018-09-08 09:31  evenbao  阅读(200)  评论(0编辑  收藏  举报