其他分享
首页 > 其他分享> > 看球的巴士——线性dp

看球的巴士——线性dp

作者:互联网

【题目描述】

两个球队的支持者要一起坐车去看球,他们已经排成了一列。我们要让他们分乘若干辆巴士,同一辆巴士上的人必须在队伍中是连续的。为了在车上不起冲突,希望两队的支持者人数尽量相等,差至多是D。有一个例外,就是一辆车上的人全部都是一个球队的支持者。问要将这N个人全部送至球场,至少要几辆巴士。

输入格式

第一行是整数N和D,1<=N<=2500,1<=D<=N。

接下来的N行,按排队的顺序,描述每个人支持的球队,用H或J表示。

输出格式

至少要几辆巴士。


 

样例

样例输入

14 3
H
J
H
H
H
J
H
J
H
H
H
H
H
H

样例输出

2

【思路分析】
     说实话一开始看见这道题觉得是区间dp,but  ……这就很尴尬了

 

     1.整个大巴上都是同一个球队的球迷,那显然(j,i)区间的长度,就是H数组或J数组在这个区间内的个数:

       合法条件为:H[j] - H[i-1] == j-i+1 || J[j] - J[i-1] == j-i+1 

     2.大巴上有两个球队的球迷,那在(i,j)区间内两个数组的差值就要小于等于D:

       合法条件为:abs(J[j]-J[i-1]-(H[j]-H[i-1])) <= d

细节见代码注释

【代码】

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N = 2500+10;
 6 int n,d;
 7 int f[N],H[N],J[N],v[N][N];
 8 int main(){
 9     scanf("%d%d",&n,&d);
10     for(int i = 1;i <= n;i++){
11         char c;scanf(" %c",&c); //注意加空格!!!
12         if(c=='H'){   //前缀和数组依次赋值
13             H[i] = H[i-1]+1;   
14             J[i] = J[i-1];
15         }
16         else{
17             J[i] = J[i-1]+1;
18             H[i] = H[i-1];
19         }
20         f[i] = i;
21     }
22     for(int i = 1;i <= n;i++){//找出可以乘坐同一辆大巴的区间
23         for(int j = i;j <= n;j++){ //关键点,注意下标不要弄错,减去的是H[i-1]或J[i-1],差值减去的也同样是i-1,才能代表(i,j)区间
24             if(H[j] - H[i-1] == j-i+1 || J[j] - J[i-1] == j-i+1 || abs(J[j]-J[i-1]-(H[j]-H[i-1])) <= d){
25                 v[i][j] = 1;
26             }
27         }
28     }
29     for(int i = 1;i <= n;i++){ //dp环节
30         for(int j= 1;j <= i;j++){
31             if(v[j][i])f[i] = min(f[i],f[j-1]+1);//这是减去j-1,查错查了半天
32         }
33     }
34     printf("%d",f[n]);
35     return 0;
36 }

标签:看球,大巴,int,球队,巴士,数组,区间,dp
来源: https://www.cnblogs.com/hhhhalo/p/12773352.html