cf-1579G Minimal Coverage (dp)

在这里插入图片描述

  • 题目大意

n个线段,每个线段长度为a[i],每个的线段的起始点是上一个线段的末位,可以向左或向右放,问这n个线段最后最小覆盖区域长度。

放到[x+1,x+a[i]],终点变为x+a[i] 
放到[x−a[i],x−1],终点变为x−a[i]
  • 题解

这题不好想dp数组的含义。
如果dp[i][j]想成第 i 个到第 j 个线段依序放置后最小的覆盖长度,不好推,没有联系
但我们看每个线段长度不超过1000,可以发现 区间覆盖的范围 就在[-1000,1000],超过1000或-1000的就可以省去了,

于是dp[i][j]是 放置前 i 个线段后,当前位置在坐标 j 时,覆盖长度的最小值
如果遇到a[i]>=j,这时要往回放,初始点也要相应移动,记录相对距离就可以。
同时这里第i个线段只与第i-1个线段有关,可以优化一下空间

const int M=1e4+7;
const int N=2e3+7;
ll T,n,a[M],dp[2][N],c,sum;
int main(){
	T=read();
	while(T--){
		n=read();	c=1;	sum=inf;
		for(int i=1;i<=n;i++)	a[i]=read();
		for(int i=0;i<N;i++)	dp[0][i]=inf;
		dp[0][a[1]]=a[1];
		for(int i=2;i<=n;i++){
			for(int j=0;j<N;j++)	dp[c][j]=inf;
			for(int j=0;j<N;j++){
				if(a[i]>=j)		dp[c][0]=min(dp[c][0],a[i]-j+dp[c^1][j]);
				else			dp[c][j-a[i]]=min(dp[c][j-a[i]],dp[c^1][j]);
				if(a[i]+j<N)	dp[c][j+a[i]]=min(dp[c][j+a[i]],max(j+a[i],dp[c^1][j]));
			}
			c^=1;
		}
		c^=1;
		for(int i=0;i<N;i++)	sum=min(sum,dp[c][i]);
		printf("%lld\n",sum);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值