3 solutions

  • 3
    @ 2022-11-7 17:36:11

    边打边移的作用:移动后,攻击后续每个位置的攻击距离变短

    但是攻击花费变少的同时移动的花费要变多

    所以我的做法是计算每个点:假如攻城炮最终移动到这个点,我们的总花费是多少

    然后比较出最小花费

    然后就要想,假如我们要移动到这个位置,花费怎么算好算呢

    我们很容易想到,要移动到某个点,一定是边打边移动花费最小,如果一直打到那个点再移动过去是比较亏的

    变打边移动的话,移动的花费就是b*该点的位置

    而这个点以前的攻击花费就是a该点位置(假如移到a3点,攻击距离=(a1-0+a2-a1+a3-a2)=a3),该点以后的攻击总距离=a4-a3+a5-a3+a6-a3+...+an-a3=(a4+a5+a6+...+an)-(a3(n-3)),而a4+a5+...+an=总前缀和-(a1+a2+a3)=总前缀和-第三个点的前缀和

    OK,上代码:

    #include<stdio.h>
    
    int x[200000];
    long long y[200000];
    
    int main()
    {
        int t;
        scanf("%d",&t);
        long long n,a,b;
        int i;
        long long num,num2,ans;
        while(t--)
        {
            num=0;
            scanf("%lld %lld %lld",&n,&a,&b);
            for(i=0;i<n;i++)
            {
                scanf("%d",&x[i]);
                num+=x[i];
                y[i]=num;//记录每个点的前缀和
            }
            ans=num*b;
            for(i=0;i<n-1;i++)
            {
                num2=(x[i]+num-y[i]-(n-i-1)*x[i])*b+x[i]*a;
    //计算如果最终移动到当前点位,移动和攻击的总花费是多少
    //x[i]为该点之前的总攻击距离,num为总前缀和,y[i]为该点的前缀和
    //n-i-1为该点之后攻击的次数,因为每次攻击都要少一个x[i]的攻击距离
                if(num2<ans)ans=num2;
            }
            printf("%lld\n",ans);
        }
        return 0;
    }
    

    Information

    ID
    839
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    8
    Tags
    # Submissions
    68
    Accepted
    9
    Uploaded By