Educational Codeforces Round 106 (Rated for Div. 2) C. Minimum Grid Path

本文介绍了一个二维坐标系路径规划问题的解决思路与算法实现。通过分析路径转弯次数的影响及奇偶性的特性,采用预处理与枚举的方法找到从起点到终点的最小消耗路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:在一个二维坐标系中,我们从(0,0)到(n,n),中途最多可以转弯n-1次,当然可以转更少次的弯,每次转弯都有一个消耗值。问到达(n,n)消耗值最小是多少?

思路:
首先,我们发现,奇数和偶数可以单独分开来,他们之间是不影响的。我们很容易就能想到我们可以枚举到达终点的转弯的位置。然后注意,这之后的都没有必要考虑了。(这是一个坑点),对于前面的,我们可以预处理出每个方向的每个位置之前出现数字的最小值。同时计算一下每次转弯的前缀和。之前的步数我们只要走一步就行了。然后剩余的步数都是由每个方向的最小值的走完即可。

这里我还想说的是,我在比赛的时候想的是我直接找出两个方向的最小值不就行了吗?然后之前的走一步,其余的最小值走。但是其实这是错误的。首先,我们某一个方向一旦到达n,那么它最多只能转一次方向了。所以即使取到了一个最小值,那么另一个方向的最小值也不一定能取到。然后,我们知道,这个题目的答案一定是对于某一个方向来说,某一个位置走若干步,其余的位置只能走一步,但是要注意的是这个走若干步的位置不一定是最后那次的,也可能是中间的某一个位置,为什么呢?因为我们这个x和y两个方向的是相互有联系的,不是单独的,所以只考虑一个方向的情况可能会错误。于是,正确的解法应该是枚举最后那次转弯,然后同时维护在这之前的最小值,让那个最小值多走,其他的只走一步就行了。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=120;
ll qk(ll a,ll b,ll p){
    if(b==0) return 1;
    if(b&1)  return a*qk(a,b-1,p)%p;
    else{
        ll mul=qk(a,b/2,p);
        return mul*mul%p;
    }
}
ll a[100010],b[100010],sum[100010];
void solve(){
    ll n;
    cin>>n;
    a[0]=1e9+7,b[0]=1e9+7;
    for(int i=1;i<=n;i++){
        ll x;
        cin>>x;
        sum[i]=sum[i-1]+x;
        a[i]=a[i-1];
        b[i]=b[i-1];
        if(i&1) a[i]=min(a[i],x);
        else b[i]=min(b[i],x);
    }
    ll ans=1e18;
    for(int i=2;i<=n;i++){
        ll s=sum[i];
        if(i&1){
            s=s+(n-i/2-1)*a[i]+(n-i/2)*b[i];
        }else{
            s=s+(n-i/2)*(a[i]+b[i]);
        }
        ans=min(ans,s);
    }
    cout<<ans<<endl;
}
int main(){
    //freopen("test.in","r",stdin);
    int t;
    cin>>t;
    while(t--){
        solve();
    }
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值