Codeforces1499-C. Minimum Grid Path (thinking + parity + greedy)

Link to the original question
Question meaning:
from (0, 0) (0,0)(0,0 ) go to(n, n) (n, n)(n,n ) , you can only go up or right at a time, and the direction must be changed. The firstiiThe cost of section i islen ∗ ci len*c_{i}l e nci, Seek the minimum cost.
The number of turns is at most n − 1 n-1n1
Thinking:
Since the direction has to be changed every time I walked, I thought about the parity discussion, and then my thinking got stuck.
Greedy didn't figure it out, only came up with adpofO (n 3) O(n^{3}) dpO ( n3 )TheDP.
The following idea is fromKingZhang, wtcl.
First,ccThe c array cannot be sorted, because there is an order when calculating the cost.
Secondly, since the direction has to be changed each time, the cost of the x-axis and the cost of the y-axis can be considered separately. In fact, the distance traveled is the same, and the specific correspondence relationship is not limited.
Then, consider how to minimize the cost. Take the cost of the x-axis as an example: Since the number of turns can be less than n-1, we can choose a minimum number to complete the journey, which will reduce the cost. But it should be noted that the number before the smallest number must be selected, which can be solved by enumeration, rather than a single definite value. Assuming that the distance of k has been traveled, the remaining distance is that the distance of nk is completed by the smallest number, so that the cost is the smallest. The former can be solved with prefix and.
The same is true for the y-axis.
Note that the above situation is only convenient for calculation. In actual walking, it is the smallest number to change the direction after a distance of n-k+1.
Code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define I_int ll
inline ll read()
{
    
    
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
    
    
        if(ch == '-')f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
    
    
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a, ll b, ll p)
{
    
    
    ll res = 1;
    while(b)
    {
    
    
        if(b & 1)res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}
const int inf = 0x3f3f3f3f;
#define PI acos(-1)
const double eps = 1e-8;
const int maxn =1e6+7;
ll n,c[maxn],a[maxn];
void solve(){
    
    
	n=read;
	a[0]=0;
	rep(i,1,n){
    
    
		c[i]=read;//花费数组
		a[i]=a[i-1]+c[i];//维护前缀和
	}
	ll tmpj=c[1],tmpo=c[2];
	ll res=n*(tmpj+tmpo);//假设不拐弯走完全程
	rep(i,3,n){
    
    
		if(i%2==1) tmpj=min(tmpj,c[i]);//分别维护最小值
		else tmpo=min(tmpo,c[i]);
		ll t=2*n-i;//总共还需要走的长度
		ll t2=t/2,t1=t-t2;//分给x轴和y轴
		res=min(res,a[i]+t2*tmpj+tmpo*t1);//a[i]表示之前的路的花费,后面两个表示到终点的花费
	}
	cout<<res<<endl;
}
int main()
{
    
    
    int T=read;
    while(T--) solve();
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45675097/article/details/114994390