zoukankan      html  css  js  c++  java
  • SP703 SERVICE_Mobile Service[动态规划]

    SERVICEMobileServiceSERVICE-Mobile-Service


    Description

    链接


    Solution

    以三个员工的位置作为状态, 第ii次询问作为阶段
    可以得出 DpDp 雏形
    dp[i,x,y,z]dp[i, x, y, z]表示完成第ii次询问, 且员工位置分别在x,y,zx, y, z时的最小花费
    考虑其能够更新的状态 :

    1. dp[i+1,Qi+1,y,z]dp[i+1, Q_{i+1}, y, z]
    2. dp[i+1,x,Qi+1,z]dp[i+1, x, Q_{i+1}, z]
    3. dp[i+1,x,y,Qi+1]dp[i+1, x, y, Q_{i+1}]

    但是以此作为状态的时空复杂度为O(QN3)O(Q*N^3), 无论是空间和时间都无法承受 .
    这时可以观察到, 当完成上一个询问时, 已经有一个员工位置确定下来了.
    于是可以设dp[i,x,y]dp[i, x, y]表示完成第ii次询问, 且员工位置分别在x,y,Quei1x, y, Que_{i-1}时的最小花费
    转移时同理 .


    Attention

    以从 xxQueiQue_i 位置为例

    容易写成
    dp[i,Quei,y]=min{dp[i1,x,y]+co[x,Quei]}dp[i, Que_{i}, y] = min{ dp[i-1, x, y] + co[x, Que_i] }
    正确的却是
    dp[i,Quei1,y]=min{dp[i1,x,y]+co[x,Quei]}dp[i, Que_{i-1}, y] = min{ dp[i-1, x, y] + co[x, Que_i] }

    错误的原因就在于没有考虑所要更新的状态会去更新哪些状态
    由于省略了一维, 在将一个员工 H 转移到新位置的时,
    H 对于i+1i+1询问来说, 相当于那个省略的一维,
    那个在 ii 询问中省略的 P员工, 对于i+1i+1询问来说, 却是没有省略的那个员工,
    所以转移新位置时将 P员工 放在已知的那个位置


    Code

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            int s = 0, flag = 1;
            char c;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    int N, M;
    int co[205][205];
    int dp[1005][205][205];
    int Que[1005];
    
    void Work(){
            N = read(), M = read();
            for(reg int i = 1; i <= N; i ++)
                    for(reg int j = 1; j <= N; j ++) co[i][j] = read();
            for(reg int i = 1; i <= M; i ++) Que[i] = read();
            memset(dp, 0x3f, sizeof dp);
            Que[0] = 3, dp[0][1][2] = 0;
            int Ans = 0x3f3f3f3f;
            for(reg int i = 1; i <= M; i ++)
                    for(reg int x = 1; x <= N; x ++)
                            for(reg int y = 1; y <= N; y ++){
                                    if(Que[i-1] == x || Que[i-1] == y || x == y) continue ;
                                    if(Que[i] != y && Que[i] != Que[i-1]){
                                            int temp = dp[i][Que[i-1]][y] = std::min(dp[i][Que[i-1]][y], dp[i-1][x][y] + co[x][Que[i]]);
                                            if(i == M) Ans = std::min(Ans, temp);
                                    }
                                    if(Que[i] != x && Que[i] != Que[i-1]){
                                            int temp = dp[i][x][Que[i-1]] = std::min(dp[i][x][Que[i-1]], dp[i-1][x][y] + co[y][Que[i]]);
                                            if(i == M) Ans = std::min(Ans, temp);
                                    }
                                    if(Que[i] != x && Que[i] != y){
                                            int temp = dp[i][x][y] = std::min(dp[i][x][y], dp[i-1][x][y] + co[Que[i-1]][Que[i]]);
                                            if(i == M) Ans = std::min(Ans, temp);
                                    }
                            }
            printf("%d
    ", Ans);
    }
    
    int main(){
            int T = read();
            while(T --) Work();
            return 0;
    }
    
  • 相关阅读:
    JS随笔
    tp5 redis 单例模式 转载
    分享我编程工作经历及对软件开发前景的看法
    redis详解(一)-- 概述
    redis详解(二)-- 数据类型详解
    redis详解(四)-- 高可用分布式集群
    redis详解(三)
    新工科平台
    关于Nginx的负载均衡
    微信退款回调
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822656.html
Copyright © 2011-2022 走看看