​传送门​

考试时竟然推出了DP , 好开心 , 和普通选连续一段的题类似 , f[i]表示 1--i 区间的最小代价

分配教室[DP]_i++=limit)" title="f[i]=f[j]+1(s1[i]-s1[j]-s2[i]+s2[j]<=M||j>=limit)" style="width: 482px; visibility: visible; height: 19px;" data-type="inline">

其中limit--i 为连续的一段 , 我们预处理一些limit , 和两种课的前缀和(s1,s2) 就可以了

分配教室[DP]_i++_02

#include<bits/stdc++.h>
#define N 2550
#define inf 0x3fffffff
using namespace std;
int n,m,a[N],l[N],s1[N],s2[N],f[N];
int read(){
int cnt=0;char ch=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read(),l[i]=i;
if(a[i]==1) s1[i]=s1[i-1]+1; else s1[i]=s1[i-1];
if(a[i]==2) s2[i]=s2[i-1]+1; else s2[i]=s2[i-1];
}
for(int i=1;i<=n;i++) if(a[i]==a[i-1]) l[i]=l[i-1];
for(int i=1;i<=n;i++){
f[i]=inf;
for(int j=l[i]-1;j<i;j++) f[i]=min(f[i],f[j]+1);
for(int j=0;j<i;j++){
if(abs(s1[i]-s1[j]-s2[i]+s2[j])<=m) f[i]=min(f[i],f[j]+1);
}
} printf("%d",f[n]); return 0;
}