zoukankan      html  css  js  c++  java
  • Grazing on the Run 题解

    【题目大意】

    大致题意就是,你的初始坐标为(x),你要去数轴上的(n)个点,问你到达所有点的时间总和最小是多少。

    直接贪心肯定不行,所以考虑(DP)

    先把坐标离散(也就是预处理两点距离(dis[i][j]=abs(a[i]−a[j]))

    接下来考虑如何dp。

    关注到一个性质,如果到目前为止,奶牛吃过最左的草堆编号为(l),吃过最右的草堆编号为(r),则如果奶牛不是傻它肯定把([l,r])的草堆都吃过了,因为它吃草速度是瞬时的,都经过了肯定要嫖一口。

    那很明显应该是个区间dp了。

    不难定义出状态(f[0/1][i][j])表示已经吃完([i,j])的草了,且现在在左端(i(0)),在右端(j(1)),所需的最少时间和。

    转移根据意义模拟一下就好了,假如我现在从区间的某端(k)转移到某点(l),则花去时间为(dis[k][l]),在这个时间内除了区间([i,j]),其他所有草堆的腐败值都增加了(1)

    具体转移顺序可以打个记搜。也可以直接循环转移——枚举区间长度,再枚举左端点。然后对于这道题内部再分类讨论一下处于左右端位置即可。时间复杂度为(O(N^2))

    #include <bits/stdc++.h>
    using namespace std ;
    const int N = 1005 , INF = 0x3f3f3f3f ;
    int n , s , st ;
    int p[ N ] ;
    int f[ N ][ N ][ 2 ] ;
    int dis[ N ][ N ] ;
    signed main () {
        scanf ( "%d%d" , &n , &s ) ;
        for ( int i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &p[ i ] ) ;
        p[ ++ n ] = s ;
        sort ( p + 1 , p + 1 + n ) ;
        for ( int i = 1 ; i <= n ; i ++ )
            for ( int j = 1 ; j <= n ; j ++ )
                dis[ i ][ j ] = dis[ j ][ i ] = abs ( p[ i ] - p[ j ] ) ;
        st = lower_bound ( p + 1 , p + 1 + n , s ) - p ;
        memset ( f , 0x3f , sizeof ( f ) ) ;
        f[ st ][ st ][ 0 ] = f[ st ][ st ][ 1 ] = 0 ;
        for ( int i = 1 ; i <= n ; i ++ ) {
            for ( int l = 1 ; l + i - 1 <= n ; l ++ ) {
                int r = i + l - 1 ;
                if ( f[ l ][ r ][ 0 ] < INF ) {
                    if ( l > 1 ) f[ l - 1 ][ r ][ 0 ] = min ( f[ l - 1 ][ r ][ 0 ] , f[ l ][ r ][ 0 ] + dis[ l ][ l - 1 ] * ( n - i ) ) ;
                    if ( r < n ) f[ l ][ r + 1 ][ 1 ] = min ( f[ l ][ r + 1 ][ 1 ] , f[ l ][ r ][ 0 ] + dis[ l ][ r + 1 ] * ( n - i ) ) ;
                }
                if ( f[ l ][ r ][ 1 ] < INF ) {
                    if ( r < n ) f[ l ][ r + 1 ][ 1 ] = min ( f[ l ][ r + 1 ][ 1 ] , f[ l ][ r ][ 1 ] + dis[ r ][ r + 1 ] * ( n - i ) ) ;
                    if ( l > 1 ) f[ l - 1 ][ r ][ 0 ] = min ( f[ l - 1 ][ r ][ 0 ] , f[ l ][ r ][ 1 ] + dis[ r ][ l - 1 ] * ( n - i ) ) ;
                }
            }
        }
        printf ( "%d
    " , min ( f[ 1 ][ n ][ 0 ] , f[ 1 ][ n ][ 1 ] ) ) ;
        return 0 ;
    }
    
    
  • 相关阅读:
    js代码编写规范
    mysql数据库的水平拆分与垂直拆分
    git使用WebHook实现自动构建
    解决php
    laravel为模型中所有查询统一添加WHERE条件
    centos7+ 安装 php7.2
    nginx配置https
    git常用命令
    php如何应对秒杀抢购高并发思路
    nginx配置优化+负载均衡+动静分离详解
  • 原文地址:https://www.cnblogs.com/hulean/p/13463118.html
Copyright © 2011-2022 走看看