zoukankan      html  css  js  c++  java
  • gmoj 6820. 【2020.10.07提高组模拟】旅游路线 (trip)

     这道题虽然没切,但还是决定写一下总结。

    因为这道题的加油是直接赋值,所以可以考虑每次枚举下一个加油的点。

    设f[i][j]表示当前到第i个点,剩余钱数为j,走的最大路程,因为路程是随钱数单调递增的,所以可以二分。

    再设一个辅助转移的数组,g[i][j][k]表示从i点走到j点,花费不超过2^k步时所能走的最大路程。

    然后就有转移:f[x][j]=max(f[y][j-p[x]]+dis[x][y])

    现在切了题,发现总结没讲完全,回来补一下。

    如果转移的时候需要注意一下细节,比如g,dis的初始值都应该赋值成-1e9,因为如果不赋初值会导致两个本来不能到达的点发生转移。

    还有就是要注意不能重复转移。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 110
    #define M 1010
    #define K 20
    #pragma GCC optimize(2)
    using namespace std;
    int n,m,C,T,i,j,k,p[N],c[N],x,y,l,q[N],f[N][N*N],dis[N][N],g[N][N][K],data[N*N*N*2][3],bz[N*N],temp[N][N],st,Q,d;
    int find(int x,int k){
        int ans=1e9,l=0,r=n*n,mid;
        while (l<=r){
            mid=(l+r)/2;
            if (f[x][mid]>=k){
                ans=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        return ans;
    }
    int main(){
        freopen("trip.in","r",stdin);
        freopen("trip.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&C,&T);
        for (i=1;i<=n;i++)
            scanf("%d%d",&p[i],&c[i]),c[i]=min(c[i],C);
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++)
                for (l=0;l<K;l++) g[i][j][l]=-1e9;
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++) dis[i][j]=-1e9;
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++) temp[i][j]=-1e9;
        for (i=1;i<=n;i++)
            g[i][i][0]=0,dis[i][i]=0;
        for (i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&l);
            g[x][y][0]=max(l,g[x][y][0]);
        }
        for (l=1;l<K;l++)
            for (i=1;i<=n;i++)
                for (j=1;j<=n;j++){
                    g[i][j][l]=g[i][j][l-1];
                    for (k=1;k<=n;k++)
                        g[i][j][l]=max(g[i][k][l-1]+g[k][j][l-1],g[i][j][l]);
                }
        for (l=0;l<K;l++){
            for (i=1;i<=n;i++)
            if (c[i]&(1<<l))
            for (j=1;j<=n;j++)
                for (k=1;k<=n;k++)
                    temp[i][j]=max(temp[i][j],dis[i][k]+g[k][j][l]);
            for (i=1;i<=n;i++)
                for (j=1;j<=n;j++)
                    dis[i][j]=max(dis[i][j],temp[i][j]);
        }
        for (l=1;l<=n*n;l++){
            for (i=1;i<=n;i++)
            if (l>=p[i])
                for (j=1;j<=n;j++)
                    f[i][l]=max(f[i][l],f[j][l-p[i]]+dis[i][j]);
        }
        while (T--){
            scanf("%d%d%d",&st,&Q,&d);
            Q-=find(st,d);
            printf("%d
    ",max(Q,-1));
        }
        return 0;
    }
  • 相关阅读:
    分布式事务框架seata入门
    生活==不易
    LR Socket接收超时TPS上不去解决方法
    Loadrunner拼装(并发用户)唯一值方法
    shell/Python复制文件和文件夹
    redis可以设置过期key回调实现延时队列
    计算机USB读写权限统一管理(在域环境中)
    微软Win10最新BUG_2021年9月15日_KB5005565更新之后打印机突然连接不上 或 不能打印0x0000011b(附解决方案)!
    SQLServer中update没带where的回滚操作(Update或者Delete误操作恢复方法)
    107.如何用Windows Defender全盘扫描
  • 原文地址:https://www.cnblogs.com/Mohogany/p/13780221.html
Copyright © 2011-2022 走看看