P1564 膜拜
P1564 膜拜
题目描述
神牛有很多…当然…每个同学都有自己衷心膜拜的神牛.
某学校有两位神牛,神牛甲和神牛乙。新入学的N 位同学们早已耳闻他们的神话。
所以,已经衷心地膜拜其中一位了。现在,老师要给他们分机房。但是,要么保证整个机房都是同一位神牛的膜拜者,或者两个神牛的膜拜者人数差不超过M。另外,现在N位同学排成一排,老师只会把连续一段的同学分进一个机房。老师想知道,至少需要多少个机房。
输入输出格式
输入格式:
输入文件第一行包括N 和M。
之后N 行,每行一个整数,1 表示神牛甲的崇拜者,2 表示神牛乙的崇拜者。
输出格式:
输出一个整数,表示最小需要机房的数量。
输入输出样例
说明
对于30%的数据,有1 ≤ N ,M≤ 50;
对于100%的数据,有1 ≤ N,M ≤ 2500。
洛谷题解
将2改为-1,题目就变成了将序列最少分为多少段,使每段和的绝对值≤M。
用简单的动态规划。
f[i]=max{f[j]}+1(|Σak|≤M) O(n²),轻松秒杀
划分动态规划
用一维数组f表示在i前最少能划分几个机房
用cha数组来储存1~i的值(如果膜拜1,++,否则--)
因为要求最小值
f初始化为0x7f,f[1]=1,即只有一个人时至少能划分1个机房
状态转移方程:
if(abs(cha[i]-cha[j-1])==i-j+1|| abs(cha[i]-cha[j-1])<=m) f[i]=min(f[i],f[j-1]+1);
我末尾一段取最大(或者说枚举末尾那一段),然后去找之前的,这样就好确定了。
1 # include<iostream> 2 # include<cstring> 3 # include<cstdlib> 4 using namespace std; 5 int n,m; 6 int a[2501]; 7 int cha[2501]; 8 int f[2501]; 9 int main() 10 { 11 cin>>n>>m; 12 for(int i=1;i<=n;i++) 13 { 14 cin>>a[i]; 15 if(a[i]==1) cha[i]=cha[i-1]+1; 16 else cha[i]=cha[i-1]-1; 17 } 18 memset(f,0x7f,sizeof(f)); 19 f[1]=1; 20 for(int i=2;i<=n;i++) 21 for(int j=0;j<i;j++) 22 { 23 int h=abs(cha[i]-cha[j-1]); 24 if(h==i-j+1||h<=m) 25 f[i]=min(f[i],f[j-1]+1); 26 } 27 cout<<f[n]; 28 return 0; 29 }
版权申明:欢迎转载,但请注明出处
一些博文中有一些参考内容因时间久远找不到来源了没有注明,如果侵权请联系我删除。
在校每年国奖、每年专业第一,加拿大留学,先后工作于华东师范大学和香港教育大学。
2024-10-30:27岁,宅加太忙,特此在网上找女朋友,坐标上海,非诚勿扰,vx:fan404006308
AI交流资料群:753014672