题目链接:https://vjudge.net/problem/CodeForces-1216F
题意:给出n个房间,k表示wifi覆盖范围。然后给出一个字符串,0表示这个房间不可以装wifi,1表示这个房间可以装wifi。每个房间都可以进行装宽带,宽带费用为i,wifi费用也为i。
解题思路:
利用f数组保存每个点i之后最近的1的位置
dp[i]表示前i个房间都被网络覆盖的最小代价
遍历所有房间,每个房间的dp[i]对应有两种来源,第一种是这个房间直接装宽带dp[i]=dp[i-1]+i;
第二种是找到前面能够覆盖它的wifi,可以知道,在覆盖i的情况下,wifi越靠前费用越少,最小能够覆盖i的wifi位置为i-k,所有找出i-k之后最近的1的位置即可,为f[i-k],记为pre=f[max(i-k,1)],pre满足的条件必须是pre<=i+k才可以覆盖i点。在满足 条件后,转移方程就是dp[i]=min(dp[i],dp[pre-k]+pre);因为在pre点建立了wifi,所有pre-k到pre+k都能被覆盖,所以转移方程为pre-k点的最小代价+pre
最后,200000!应该会超int范围,记得用long long
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define ll long long
int n,k;
char s[210000];
int f[210000];
ll dp[210000];
int main(){
cin>>n>>k;
scanf("%s",s+1);
f[n+1]=3*n;
for(int i=n;i>0;i--){
f[i]=(s[i]=='1')?i:f[i+1];
}
dp[0]=0;
for(int i=1;i<=n;i++){
dp[i]=dp[i-1]+i;
int pre=f[max(1,i-k)];
if(pre<=i+k){
dp[i]=min(dp[i],dp[max(pre-k,1)-1]+pre);
}
}
printf("%lld\n",dp[n]);
return 0;
}