1. 程式人生 > >【dp】分配教室

【dp】分配教室

傳送門

一道線性dp,,程式碼+讀優 40排qwq

上程式碼+註釋

#include<bits/stdc++.h>
#define in read()
using namespace std;
int in{
	int cnt=0,f=1;char ch=0;
	while(!isdigit(ch)){
		ch=getchar();
		if(ch=='-')f=-1;
	}
	while(isdigit(ch)){
		cnt=cnt*10+ch-48;
		ch=getchar();
	}
	return cnt*f;
}
int n,m;
int a[2503];
int f[2503];
int sum1[2503],sum2[2503];//1個數的字首和,2的字首和 
int main(){
	n=in;m=in;
	for(int i=1;i<=n;i++){
		a[i]=in;
		sum1[i]=sum1[i-1];sum2[i]=sum2[i-1];
		if(a[i]==1)sum1[i]++;
		else sum2[i]++;
	}
	memset(f,0x3f,sizeof(f));//初始很大 ,f[i]表示1~i這些人用的最少教室 
	f[0]=0;//0個人自然0間教室 
	for(int i=1;i<=n;i++){
		for(int j=1;j<i;j++){//列舉j~i的人放一間教室 
			if(abs(sum1[i]-sum1[j-1]-sum2[i]+sum2[j-1])<=m||sum1[i]-sum1[j-1]==0||sum2[i]-sum2[j-1]==0){
				//分別是:人數差<=m,全部是2的粉絲,全部是1的粉絲。 
				f[i]=min(f[i],f[j-1]+1);
			}
		}
		if(f[i]==f[i+1])f[i]=f[i-1]+1;//注意,如果之前沒有可更新情況,那說明
		//這個人要單獨用一間教室,故直接等於上一個人+1 
	}
	cout<<f[n]<<endl;
	return 0;
}