DESCRIPTION
有n个灯,初始时都是不亮的状态,每次你可以选择一个某一个灯,不妨记为x,所有满足和x距离不超过k的灯的状态都将被翻转,选择第i个灯的代价记为ci,问最终所有灯都是亮的状态的最小花费.
INPUT
输入有两行,第一行包含两个正整数
n(1≤n≤10000)和k(0≤k≤1000)第二行包含
n个整数,分别表示
ci(0≤ci≤109)
OUTPUT
输出一行表示答案
SAMPLE INPUT
3 11 1 1
SAMPLE OUTPUT
1
SOLUTION
题解: 其实确定一个起点后面的状态都是确定的了,起点很明显是k+1个。
那么枚举前k+1个起点,求出最小结果就行了。
注意最后不足(2*k+1)的数量的灯必须大于k才合法,否则不合法。
起初枚举的时候,每个点后面是一位一位向后推的,莫名一直错,,最后改成2*k+1个往后推,就对了。
官方题解:
对于每一次的操作,显然其周围的2k个灯不会有状态翻转,否则这次就是无效的,于是转换为简单的动态规划 问题.
令dp(i)表示将前i+k个灯全部点亮的最小花费,直接转移即可.
复杂度为O(n)。
令dp(i)表示将前i+k个灯全部点亮的最小花费,直接转移即可.
复杂度为O(n)。
。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e4+100;
const int inf=0xfffffff;
int n,k;
ll ans;
int a[maxn];
int main(){
cin>>n>>k;
ll q=1e17;
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
if(k==0) {
for(int i=1;i<=n;++i) ans+=a[i];
cout<<ans<<endl;
return 0;
}
int len=min(k+1,n);
for(int i=1;i<=len;++i){
ans=a[i];
int t=i+k;
if(t>=n) {q=min(q,ans);continue;}
int con=n-t;
int j;
for(j=i+2*k+1;j<=n;j+=2*k+1) ans+=a[j];
if(j-n>=k+1) q=min(q,ans);
}
cout<<q<<endl;
return 0;
}