vijos-p1331 2008.11.6
描述 Description
两个球队的支持者要一起坐车去看球,他们已经排成了一列。我们要让他们分乘若干辆巴士,同一辆巴士上的人必须在队伍中是连续的。为了在车上不起冲突,希望两队的支持者人数尽量相等,差至多是D。有一个例外,就是一辆车上的人全部都是一个球队的支持者。问要将这N个人全部送至球场,至少要几辆巴士。
输入格式 Input Format
第一行是整数N和D,1<=N<=2500,1<=D<=N。
接下来的N行,按排队的顺序,描述每个人支持的球队,用H或J表示。
输出格式 Output Format
至少要几辆巴士。
样例输入 Sample Input
143
H
J
H
H
H
J
H
J
H
H
H
H
H
H
样例输出 Sample Output
2
分析:
g[i]表示从1到i的H与J相差的人数,注意:g[i]>=0;
设f[i]为前i个支持者需要坐的最少车数:f[i]=min{f[j]}+1;(0<=j<i)
为什么要这样写方程呢?f[j]表示1-j这些人最少要用的车数,那么我们就要从
j+1~i这些人中去考察,看他们是不是可以搭乘一辆车,若可以的话,那么就必须满足下面条件的其中一个:
1)abs(g[i]-g[j])<=d 差<=d
2)abs(g[i]-g[j])=i-j j+1~i这些人,是支持同一个队伍的,仔细想一想,就是这样的。
所以,我们就要从0~i-1(当j=0时,1~i这些人有可能都是同一队的)去考察,选择最小的,满足条件的j,就得到了这个方程~~
感受:
在做dp时,可能会对数据进行一些处理,还有可能一些很奇特的性质,或是简化成模型来解题
program p1331;
const fin='in.in';fout='out.out';
var f1:text;
f,g:array[0..2500]of longint;
n,d,i,j:longint;
procedure init;
var i:longint;ch:char;
begin
readln(n,d);fillchar(f,sizeof(f),0);
fillchar(g,sizeof(g),0);
for i:=1 to n do
begin
readln(ch);
if ch='H' then g[i]:=g[i-1]+1 else g[i]:=g[i-1]-1;
end;{计算差值的巧妙方法}
for i:=1 to n do g[i]:=abs(g[i]){不要忘了取绝对值}
end;
procedure doit;
var i,j,p:longint;
begin
for i:=1 to n do
begin p:=maxlongint;
for j:=0 to i-1 do
begin
if (abs(g[i]-g[j])<=d) and (f[j]<p) then p:=f[j];
if (abs(g[i]-g[j])=i-j) and (f[j]<p) then p:=f[j];
end;
if p<>maxlongint then f[i]:=p+1;
end;
writeln(f[n]);
end;
begin init; doit;end.