一个直线上有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