【CF】CF1430_F Realistic Gameplay_dp

链接

codeforces 1430F

题面

题解

  • 我们记第i波的实际控制范围为([l_i,min(r_i,l_{i+1}-1])。记(f_i)表示在第i波实际控制范围内把前面的所有怪物都打死至少浪费多少子弹。
  • 每次直接(O(n))往后转移即可。
  • 实际上是可以不用(r_ileq l_{i+1})的,只用保证(l_ileq l_{i+1},r_ileq 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
",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
",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;
}
原文地址:https://www.cnblogs.com/czyarl/p/13832409.html