思路:
条件:照亮[0,n]段,选一种灯泡订购,灯泡有价格和向后照射长度,设置了不能放置的位置
1、计算可以选择的最短长度,因为有blocked,因此必须从其前一格放置灯,并且覆盖blocked区域。
计算blocked 的方法:
(1) [0,1,2,3,4,5,6] 3,4,5 不能用,必须选择长度大于等于[2,6] = 4
(2)[0,1,2,3,4,5,6] 0 不能用[0,1] 肯定照射不到 输出-1
(3)[0,1,2,3,4] 覆盖长度max([1,3],[3,4])
取最小花费:
遍历K,从max_blocked 开始计算花费:
如 [0,.....,n] ,给定K,从位置i,走K步i+K,i=i+K ,一直到 i>=n
期间如果i = is blocked,需要blocked 得到blocked前面第一个非blocked。(这里在输入的时候记录一下就好了)
代码:
C++ 11
#include<bits/stdc++.h>
using namespace std;
int s[1000000+10],sl[1000000+10];
bool vis[2000000+10];
int a[1000000+10];
struct price
{
int a;//单价
int l;//可照明长度
}P[1000000+10];
int main() {
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
int max_block=0,l=1;
memset(vis,0,sizeof(vis));
memset(s,-1,sizeof(s));
for(int i=0;i<m;i++){
scanf("%d",&s[i]);
vis[s[i]] = 1;
if(i==0) {
sl[s[i]] = s[i] -1;
continue;
}
if(s[i]==s[i-1]+1) {
l += 1;
sl[s[i]] = sl[s[i-1]];
}
else{
max_block = max(l+1,max_block);
sl[s[i]] = s[i]-1;
l = 1;
}
}
int x = 0;
if(l>1&&s[m-1]==n) max_block = max(l,max_block);
else if(l>1) max_block = max(l+1,max_block);
else if(m==1&&s[m-1]==n) max_block =max(l,max_block);
else if(m==1) max_block =max(l+1,max_block);
for(int i=0;i<k;i++) {
scanf("%d",&a[i]);
if(i+1>=max_block) {
P[x].a = a[i],P[x].l = i+1,x++;//只能选这些
}
}
if(max_block>k||s[0]==0) printf("-1\n");
else{
long long ans = 1e13;
for(int i=0;i<x;i++){
long long tmp = 0;
int r =0;
while(r<n){
tmp += P[i].a;
r = r+P[i].l;
if(vis[r]==1) r = sl[r];
}
ans = min(ans,tmp);
}
printf("%lld\n",ans);
}
return 0;
}