洛谷P2389 电脑班的裁员【DP】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/82792914

时空限制 1000ms / 128MB

题目描述

ZZY有独特的裁员技巧:每个同学都有一个考试得分ai(-1000<=ai<=1000),在n个同学(n<=500)中选出不大于k段(k<=n)相邻的同学留下,裁掉未被选中的同学,使剩下同学的得分和最大。要特别注意的是,这次考试答错要扣分【不要问我为什么】,所以得分有可能为负。

输入格式:

第一行为n,k,第二行为第1~n位同学的得分。

输出格式:

一个数s,为最大得分和。


题目分析

题目数据范围真的迷,n^2 太小,n^3 太大
d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] 分别表示 i i 个同学留下 j j ,且 i i 个同学不留(0)/留(1)的最大分数
转移方程为
d p [ i ] [ j ] [ 0 ] = m a x ( d p [ i 1 ] [ j ] [ 0 ] , d p [ i 1 ] [ j ] [ 1 ] ) dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1])
d p [ i ] [ j ] [ 1 ] = m a x ( d p [ i 1 ] [ j ] [ 1 ] , d p [ i 1 ] [ j 1 ] [ 0 ] ) + a [ i ] dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0])+a[i]


#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

const int maxn=510;
int n,k;
int a[maxn],dp[maxn][maxn][2];

int main()
{
    n=read();k=read();
    for(int i=1;i<=n;++i) a[i]=read();
    
    for(int i=1;i<=n;++i)
    for(int j=1;j<=k;++j)
    dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]),
    dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0])+a[i];
    
    printf("%d",max(dp[n][k][1],dp[n][k][0]));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/niiick/article/details/82792914