引子:
为什么要写这道题呢?这道题虽然简单,但是我觉得我想写屁话!,因为这道题呢,有一些细节真的是值得我们去关注的。
思路:
因为是要求可以拉最大的人数,而且必须是连续且从走往右的所以,这道题的大体可以往最长上升子序列那边思路想。
所以状态转移方程应该是:
dp[i][j] = max(dp[i][j - 1],dp[i - 1][j - m] +b[j] - b[j - m]);
这个方程的意思是在第i个车头时可以拉j个车厢。
注意有一个细节!第一层循环是枚举车头的数量
for(int i=1;i<=3;i++)
第二层循环呢是枚举,在第i火车头时,拉m个车厢能拉的最多人
for(int j=m;j<=n;j++)
问题来了:为什么j要从m开始呢?
因为题目告诉了啊>_<
一个正整数m,代表能够被单一火车头拉动的最大火车厢个数
那么为什么j<=n呢?
因为题目也告诉了啊>_<
所以目标就是在当第三个车头的时候拉n个车厢才能保证拉的人数最多。
所以最后输出应该是
printf("%d\n",dp[3][n]);
代码:
//QAQ
#include<cstdio>
#include <cstring>
#include<algorithm>
using namespace std;
int dp[5][50005],a[50005],b[50005];
int max(int x,int y){
if (x>y) return x;
else return y;
}
int main(){
int m,t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=b[i-1]+a[i];
}
scanf("%d",&m);
for(int i=1;i<=3;i++){
//枚举第i个火车头
for(int j=m;j<=n;j++){
//第i火车头时,必须拉m个来能拉最多人(3*m<=n)
dp[i][j] = dp[i][j - 1];
dp[i][j] = max(dp[i][j - 1],dp[i - 1][j - m] +b[j] - b[j - m]);
}
}
printf("%d\n",dp[3][n]);
}
return 0;
}