过河

 

思路:线性动态规划(这题的状态转移很有特点)

我们先将所有人按花费时间递增进行排序,假设前 ii 个人过河花费的最少时间为 opt[i]opt[i],那么考虑前 i-1i1 个人已经过河的情况,

即河这边还有 11 个人,河那边有 i-1i1 个人,并且这时候手电筒肯定在对岸,所以 opt[i] = opt[i-1] + a[1] + a[i]opt[i]=opt[i1]+a[1]+a[i

(让花费时间最少的人把手电筒送过来,然后和第 ii 个人一起过河) 。如果河这边还有两个人,一个是第 ii 号,另外一个无关,河那边有 i-2i2 个人,并且手电筒肯定在对岸,所以

 opt[i] = opt[i-2]opt[i]=opt[i2+a[1] + a[i] + 2* a[2]a[1]+a[i]+2*a[2](让花费时间最少的人把电筒送过来,然后第 ii 个人和另外一个人一起过河,

由于花费时间最少的人在这边,所以下一次送手电筒过来的一定是花费次少的,送过来后花费最少的和花费次少的一起过河,解决问题),

所以opt[i]=min(opt[i1]+a[1]+a[i],opt[i2]+a[1]+a[i]+2×a[2])

 

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std ;

const int N = 1010 ;

int a[N] ;
int f[N] ;
int n ;

int main(){
    cin >> n ;
    for(int i=0;i<n;i++){
        cin >> a[i] ;
    }
    sort(a,a+n) ;
    
    for(int i=0;i<n;i++){
        if(i == 0){
            f[i] = a[i] ;
        }else if(i == 1){
            f[i] = max(a[i],a[i-1]) ;
        }else{
            f[i] = min(f[i-1]+a[0]+a[i],f[i-2]+a[i]+2*a[1]+a[0]) ;
        }
    }
    cout << f[n-1] << endl ;
    
    return 0 ;
}

 

posted @ 2020-03-12 20:48  gulangyuzzz  阅读(158)  评论(0编辑  收藏  举报