vijos-p1331 2008.11.6

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.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值