Codeforces 1499C. Minimum Grid Path(前缀和,思维优化)

题目链接

题意:

给出你一个n*n的二维地图,让你从(0,0)走到(n,n)规定:

  1. 只能向右和向上走,并且向右向上交替进行。
  2. 每次可以连着走几段,每次走都有一个代价 a i a_i ai(单位长度的代价 )i表示第几次走
  3. 最后的总代价是每一段走的总代价和。

让你求最小的代价、

思路:

一开始就想到了前缀和优化,只不过一开始光集中的想这最后两步走长点,这样就可以保证一维度最优,另一位都,就不是最优的。简单的说一下,虽然不是正解,但可以从中挖掘(提炼)出正解,就是说我们一共最多要走的是2N单位长度,那么我们维护一维最优的化就是,但我们考虑 i i i次走时。那么我们前面一共是走了 i − 1 i-1 i1次,我们再往前推一步,就是 i − 2 i-2 i2那么我们就可保证前面 i − 1 i-1 i1次都走一单位,最后两步 i 和 i − 1 i和i-1 ii1 一定能走到终点。那么i-1走多少步那一共是2n走了i-2步剩 ( 2 ∗ n − i + 2 ) = s u m (2*n-i+2)=sum (2ni+2)=sum步先走的,那么 i − 1 i-1 i1需要走(sum+1)/2步,i需要走 (sum/2)步。

这就是 单方面一维最优。但是我们保证一维最优,另一维却不一定是最优的。所以说不是正解却能启发我们想到正解。

正解:是二维度最优,我们保证二维都是最小的走的步数最多即可保证最终答案最优。所以需要维护二维中的最小值。那我们每次都都比较,记录一下最小值不就行了,然后维护一次前缀因为前面每一个最小都是需要走一段的。我们再加上两位都最小值还需要走的步数(走到终点),比较取最小值即可。

下面注释的是我原本的错解,看着理解下,提炼出正解嘻嘻。
晚安好梦各位。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
ll a[maxn], b[maxn],c[maxn];
ll n, m, cnt, k1, k2;
map<ll, ll> mp;
ll maxx;
string str;
int main()
{
    
    
    ll t;
    cin >> t;
    while(t--)
    {
    
    
        cin >> n;
        b[0]=0;
        for (int i = 1; i <= n; ++i)
        {
    
    
            cin >> a[i];
            b[i] = b[i - 1] + a[i];
        }
        ll ji=a[1],ou=a[2];        
        maxx =n*a[1]+n*ou;
        ll ans=2*n;
        for(int i=3;i<=n;i++){
    
    
            if(i%2)ji=min(ji,a[i]);
            else ou=min(ou,a[i]);
            ll p,q;
            ll sum=ans-i;
            p=(sum+1)/2;
            q=sum/2;
            maxx=min(maxx,b[i]+q*ji+p*ou);
        }



        /*ll ans = 2 * n;
        for(int i = 2; i <= n; i++)
        {
            ll sum = ans - i + 2;
            ll p, q;
            p = sum / 2;
            q = (sum + 1) / 2;
            maxx = min(maxx, b[i - 2] + q * a[i - 1] + p * a[i]);
        }*/
        cout << maxx << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45911397/article/details/114994481