zoukankan      html  css  js  c++  java
  • hdu 4362 Dragon Ball

    题意:在M分钟里,每分钟会出现N颗龙珠,每颗龙珠的位置有题目给出,并且取走每个龙珠所消耗的能量也给出,同时在路上消耗的能量石|x1-x2|,如果在每分钟出现的龙珠里取一颗,问消耗能量最小是多少。

    思路:在比赛的时候就知道要有dp过,不过如果是不加优化的dp会超时的,所以要优化一下。先来推一下dp的状态转移公式。设dp[i][j]表示第i批龙珠中取第j个需要花费的最小体力。dp[i][j] = min{ dp[i-1][k] + abs(pos[i-1][k]-pos[i][j]) } + cost[i][j];

    如果直接用这个状态转移公式的,时间复杂度是:m*n*n,优化的话,如果每一个状态都看成是由它左边的位置转移来的话,状态转移公式可以转变成:

    p[i][j] = min { dp[i-1][k] + pos[i][j] - pos[i-1][k] } + cost[i][j]  = min { dp[i-1][k] - pos[i-1][k] } + pos[i][j] + cost[i][j]

    因为dp[i-1][k]-pos[i-1][k]是个确定的值,就是相当于求位置在pos[i][j]左边的上一层状态中值最小的,同理可得由它右边位置转移而来的,两者去最小。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <math.h>
    #define  N 1002
    #define  M 53
    #define  INF 100000000
    using namespace std ;
    
    struct node
    {
        int pos ;
        int cost ;
    }p[M][N] ;
    
    int dp[M][N] ;
    int q[N] , top , tail ;//单调队列维护最小值
    
    int cmp ( const node &a , const node &b )
    {
        return a.pos < b.pos ;
    }
    
    int cal ( int i , int k , int j )//求距离
    {
        return dp[i-1][k] + abs( p[i-1][k].pos - p[i][j].pos );
    }
    
    int main()
    {
        int cas , i , j , k , n , m , s , minx , res ;
    
        scanf ( "%d" , &cas );
        while ( cas-- )
        {
            scanf ( "%d%d%d" , &m , &n , &s );
            for ( i = 0 ; i < m ; i++ )
            {
                for ( j = 0 ; j < n ; j++ )
                scanf( "%d" , &p[i][j].pos );
            }
            for ( i = 0 ; i < m ; i++ )
            {
                for ( j = 0 ; j < n ; j++ )
                {
                    scanf ( "%d" , &p[i][j].cost );
                }
                sort( p[i] , p[i] + n , cmp );//将位置从小到大排序
            }
    
            for ( i = 0 ; i < n ; i++ )//初始化
            dp[0][i] = abs ( s - p[0][i].pos ) + p[0][i].cost ;
    
            for ( i = 1 ; i < m ; i++ )
            {
                top = 0 ;
                tail = -1 ;
                //从左边开始搜索
                for ( j = k = 0 ; j < n ; j++ )
                {
                    dp[i][j] = INF ;
                    //找最小值,有单调队列维护
                    while ( k < n && p[i-1][k].pos <= p[i][j].pos )
                    {
                        res = cal ( i , k , j );
                        while ( tail >= top && cal( i , q[tail] , j ) >= res )
                        tail-- ;
                        q[++tail] = k ;
                        k++ ;
                    }
                    if ( tail >= top )//取第一个最小值
                    dp[i][j] = cal ( i , q[top] , j );
                }
    
                top = 0 ;
                tail = -1 ;
                //从右边开始搜索
                for ( j = k = n - 1 ; j >= 0 ; j-- )
                {
                    while ( k >= 0 && p[i-1][k].pos > p[i][j].pos )
                    {
                        res = cal ( i , k , j );
                        while ( tail >= top && cal ( i , q[tail] , j ) >= res )
                        tail-- ;
                        q[++tail] = k ;
                        k-- ;
                    }
                    if ( tail >= top )
                    {
                        if ( cal ( i , q[top] , j ) < dp[i][j] )
                        dp[i][j] = cal ( i , q[top] , j );
                    }
                }
                for ( j = 0 ; j < n ; j++ )
                dp[i][j] += p[i][j].cost ;
            }
            minx = INF ;//找最小值
            for ( i = 0 ; i < n ; i++ )
            if ( dp[m-1][i] < minx )
            minx = dp[m-1][i] ;
            printf ( "%d\n" , minx );
        }
        return 0 ;
    }
  • 相关阅读:
    Luogu 4841 城市规划
    Luogu 4721 【模板】分治 FFT
    Luogu 4091 [HEOI2016/TJOI2016]求和
    Luogu 3723 [AH2017/HNOI2017]礼物
    FFT笔记
    Luogu 4900 食堂
    Luogu 4155 [SCOI2015]国旗计划
    Luogu 4069 [SDOI2016]游戏
    Luogu 4254 [JSOI2008]Blue Mary开公司
    Luogu 4251 [SCOI2015]小凸玩矩阵
  • 原文地址:https://www.cnblogs.com/misty1/p/2643526.html
Copyright © 2011-2022 走看看