监狱
Time Limit:10000MS Memory Limit:65536K
Total Submit:109 Accepted:56
Case Time Limit:1000MS
Description
TECH在执行刺杀计划的过程中被警方抓捕,被送到了一座监狱。与TECH同时入狱的共有N位罪犯。这些罪犯有的是白人,有的是黑人。狱警要给他们分房间。但是,监狱为减少不必要的冲突,要求:要么保证整个房间都是同一肤色的罪犯,或者同一房间两种不同肤色罪犯的人数差不超过M。另外,现在N个罪犯被锁链拴成成一排,狱警只会把连续一段的罪犯分进一个房间。狱警想知道,至少需要多少个房间(假设每个房间可容纳无限罪犯,同时假设TECH是黑人)。
Input
第一行包括N和M。
之后N行,每行一个整数,代表罪犯的肤色,1表示白色,2表示黑色。
Output
一个整数,表示最小需要房间的数量。
Sample Input
12 1
1
1
1
1
2
1
2
1
1
2
2
2
Sample Output
2
Hint
对于30%的数据,有1 ≤ N ,M≤ 50;
对于60%的数据,有1 ≤ N ,M≤ 1000;
对于100%的数据,有1 ≤ N,M ≤ 2500。
Source
一道有点意思的动规,用f[i]表示前i个人所需的最小监狱数量,用前缀和分别求出i之前的黑人白人的数量b[i]和w[i]
状态转移方程f[i]=min(f[j-1])+1 即第j到第i个人分在同一个房间
注意条件:abs(w[i]-w[j]-b[i]+b[j])<=M或w[i]-w[j]==0或b[i]-b[j]==0,0<=j<i
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
const int INF=999999999;
int N,M;
int v[2505],w[2505],b[2505],f[2505];
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
f[i]=INF;
scanf("%d",&v[i]);
}
int i,j;
for(i=1;i<=N;i++){
w[i]=w[i-1];
b[i]=b[i-1];
if(v[i]==1) w[i]++;
else b[i]++;
}
for(i=1;i<=N;i++){
int temp=INF;
for(j=0;j<=i;j++)
if(abs(w[i]-w[j]-b[i]+b[j])<=M||w[i]-w[j]==0||b[i]-b[j]==0)
temp=min(temp,f[j]);
f[i]=temp+1;
}
printf("%d",f[N]);
}