链接
codeforces 1430F
题面
题解
- 我们记第i波的实际控制范围为\([l_i,\min(r_i,l_{i+1}-1]\)。记\(f_i\)表示在第i波实际控制范围内把前面的所有怪物都打死至少浪费多少子弹。
- 每次直接\(O(n)\)往后转移即可。
- 实际上是可以不用\(r_i\leq l_{i+1}\)的,只用保证\(l_i\leq l_{i+1},r_i\leq r_{i+1}\)。
代码
#include<bits/stdc++.h>
#define LL long long
#define MAXN 2010
#define INF 100000000000000
using namespace std;
template<typename T> void Read(T &cn)
{
char c; int sig = 1;
while(!isdigit(c = getchar())) if(c == '-') sig = 0;
if(sig) {cn = c-48; while(isdigit(c = getchar())) cn = cn*10+c-48; }
else {cn = 48-c; while(isdigit(c = getchar())) cn = cn*10+48-c; }
}
template<typename T> void Write(T cn)
{
int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
if(cn < 0 || cx < 0) {putchar('-'); cn = 0-cn; cx = 0-cx; }
while(cn)cm = cm*10+cn%10,cn/=10,wei++;
while(wei--)putchar(cm%10+48),cm/=10;
putchar(cx+48);
}
template<typename T> void WriteL(T cn) {Write(cn); puts(""); }
template<typename T> void WriteS(T cn) {Write(cn); putchar(' '); }
template<typename T> void Max(T &cn, T cm) {cn = cn < cm ? cm : cn; }
template<typename T> void Min(T &cn, T cm) {cn = cn < cm ? cn : cm; }
int n;
LL k;
int a[MAXN+1], l[MAXN+1], r[MAXN+1];
LL f[MAXN+1];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Read(n); Read(k);
for(int i = 1;i<=n;i++) Read(l[i]), Read(r[i]), Read(a[i]);
for(int i = 1;i<=n;i++) f[i] = INF; f[0] = 0;
for(int i = 0;i<=n-1;i++)
{
// printf("f[%d] = %lld\n",i,f[i]);
int lef_bu = k, lef_mo = 0;
for(int j = i+1;j<=n;j++)
{
if(lef_bu+k*(r[j]-l[j]) < lef_mo+a[j]) break;
if(j == n) {Min(f[j], f[i]); break; }
int br = min(l[j+1]-1, r[j]);
if(lef_bu+k*(br-l[j]) >= lef_mo+a[j]) {
lef_bu = (lef_bu+k*(br-l[j])-lef_mo-a[j])%k, lef_mo = 0;
if(lef_bu == 0) lef_bu = k;
Min(f[j], f[i]+lef_bu);
}
else {
if(r[j] == l[j]) lef_mo = lef_mo+a[j];
else lef_mo = lef_mo+a[j]-lef_bu-k*(br-l[j]), lef_bu = k;
}
// printf(" j = %d lef_mo = %d lef_bu = %d\n",j,lef_mo,lef_bu);
}
}
if(f[n] >= INF) {puts("-1"); return 0; }
for(int i = 1;i<=n;i++) f[n] = f[n]+a[i];
WriteL(f[n]);
return 0;
}