补丁题 n=1e6难度1800 n=1e3 难度1500(思维 dp)

一个直线上有n个漏洞,你有两种补丁,长度分别为A和B,给你所有漏洞的位置,问把这些漏洞全部补上,需要的最小补丁长度和是多少?(与漏洞所在位置无关 i代表第几个漏洞 位置可1e9 与n有关)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cctype>
using namespace std;

#define PI acos(-1.0)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;	
const int INF32M=0x3f3f3f3f;
const ll INF64M=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+5;
int pos[maxn],dp[maxn];//n个洞的位置 补到当前洞的最小补丁长度和 
/*数组最大开1e6  1s 1e8 n=1e6 跑o(n)
总共有n个补丁 最大1e6 此时不能枚举上一次
A种补丁B种补丁编号 n^2复杂度 只能n=1e3
n=1e6 o(n^2)=1e12 
A补丁长度=5 补1-5 但能补最大距离d=4<A;
B补丁长度=8 补1-8 能补最大距离d=7<B */
int main()
{
	ios::sync_with_stdio(false);
	int n,A,B,j=0,k=0;
	cin>>n>>A>>B;	//A种补丁 B种补丁长度
	memset(dp,0,sizeof dp);
	dp[0]=0;
	for(int i=1;i<=n;i++)
		cin>>pos[i];	//编号对应位置
	for(int i=1;i<=n;i++)
	{
		while(pos[i]-pos[j+1]>=A)	//上一次的状态
			j++;	
		while(pos[i]-pos[k+1]>=B)
			k++;	//	距离太远 补丁个数++
		dp[i]=min(dp[j]+A,dp[k]+B); //j,k上一次补到第几个洞 对应补丁最小长度 
	 }
	 //for(int i=1;i<=n;i++)
	 // 	cout<<dp[i]<<" ";
	 cout<<dp[n]<<endl;	//编号为n最后一个漏洞补后 总共所需补丁最短长度 
	return 0;
}

n=5 A=5 B=8
1 5 6 10 14
dp 5 5 8 10 13
i=3 j=1 k=0
i=4 j=2 k=1
i=5 j=3 k=2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值