Problem 4 聪明伶俐的香穗子
香穗子遇到难题了.
题目是这样的,一个序列上有n个整数,现在你要取m个,且这m个数的任意两个不能相隔的太近,否则这样会太丑,现在问你最大能得到多大的和
输入:
第一行三个数n,m,k,分别表示n个数,取m个,且m个中的任意两个位置差要大于等于K
接下来一行,有n个整数,表示序列上的每个数
输出:
最大和
Sample Input
4 2 2
3 4 -5 1
Sample Output
5
数据范围:
n<=10000,m<=100,m<=n
答案保正小于 Maxlongint
这道题真的坑爹……
考试的时候只对了几组
方程很好想 其实
用F[i][j] 表示前I个数 取j个数的最大值
分两种情况 取不取第i个数
如果要取 则F[i][j] = F[i - K][j - 1] + A[i]
if not, F[i][j] = F[i - 1][j]
but you know that i must be larger than k…
so...
F[i][j] = F[i - 1][j];
if (i > k)
{
F[i][j] = max(F[i][j], F[i - K][j - 1]);
}
and you know that CPP do not support numbers which are less than zero
so we must move the array
like this
F[i + 10005][j]
as it code is bellow
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int N, M, K;
int A[10005];
int F[10005 + 10005][105];
void init_file()
{
freopen("4.in", "r", stdin);
freopen("4.out", "w", stdout);
}
void read_data()
{
memset(F, -0x3f, sizeof F);
scanf("%d%d%d", &N, &M, &K);
for(int i = 1; i <= N; i++)
{
scanf("%d", &A[i]);
if (A[i] > F[i - 1 + 10005][1])
{
F[i + 10005][1] = A[i];
}
else F[i + 10005][1] = F[i + 10004][1];
}
}
void work()
{
for(int i = 1; i <= N; i++)
for(int j = 2; j <= M; j++)
{
F[i + 10005][j] = F[i + 10004][j];
if (i > K)
{
F[i + 10005][j] = max(F[i + 10005][j], F[i - K + 10005][j - 1] + A[i]);
}
}
printf("%d\n", F[N + 10005][M]);
}
int main()
{
init_file();
read_data();
work();
return 0;
}