【AtCoder】AGC004 Colorful Slimes

题目

传送门

题目大意

这里有 N N N只颜色为 1 , 2 , . . . , N 1,2,...,N 1,2,...,N的史莱姆,Snuke想每种颜色的史莱姆抓一只,他直接抓颜色为 i i i的史莱姆需要 a i a_i ai秒,他还可以花 X X X秒施展一个咒语,使他已经抓住的所有史莱姆的颜色加 1 1 1(颜色为 N N N的史莱姆颜色变成 1 1 1),问达成目标最少需要多少秒。

思路

如果你规定施展 k k k次咒语,那么抓住第 i i i只史莱姆可以通过抓住第 i i i只、第 i − 1 i-1 i1只、……第 i − k + 1 i-k+1 ik+1只或第 i − k i-k ik只(循环计数)得到。例如,你要施展 2 2 2次咒语,捉住第 3 3 3只史莱姆,就有三种办法:

  • 1 1 1 → \to 施展咒语 → \to 施展咒语
  • 施展咒语 → \to 2 2 2 → \to 施展咒语
  • 施展咒语 → \to 施展咒语 → \to 3 3 3

所以对于第 i i i只史莱姆,代价 C ( i , k ) = min ⁡ j = i − k i a j C(i,k)=\min\limits_{j=i-k}^{i}a_j C(i,k)=j=ikminiaj,于是答案为: k X + ∑ i = 1 N C ( i , k ) kX+\sum\limits_{i=1}^{N}C(i,k) kX+i=1NC(i,k)
枚举 k k k,如果暴力计算 C ( i , k ) C(i,k) C(i,k),时间复杂度 O ( N 2 ) O(N^2) O(N2)

想想可以发现, C ( i , k ) C(i,k) C(i,k)能递推: C ( i , k ) = min ⁡ { C ( i , k − 1 ) , a i − k } C(i,k)=\min\{C(i,k-1),a_{i-k}\} C(i,k)=min{C(i,k1),aik}
做完了。

代码

#include<cstdio>
#include<algorithm>
using namespace std;

#define MAXN 2000
int N,X;
int Cost[MAXN+5],Change[MAXN+5][MAXN+5];

int main(){
    scanf("%d%d",&N,&X);
    for(int i=1;i<=N;i++)
        scanf("%d",Cost+i);
    long long Ans=1ll<<60,tot=0;
    for(int i=1;i<=N;i++)
        tot+=Change[i][0]=Cost[i];
    Ans=min(Ans,tot);//k=0的时候单独算,不然递推会越界
    for(int k=1;k<N;k++){
        tot=0;
        for(int i=1;i<=N;i++)
            tot+=Change[i][k]=min(Change[i][k-1],Cost[i-k<1?N+i-k:i-k]);//注意循环
        Ans=min(Ans,1ll*k*X+tot);
    }
    printf("%lld",Ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值