聪明伶俐的香穗子
Time Limit:10000MS Memory Limit:65536K
Total Submit:23 Accepted:14
Description
香穗子遇到难题了.
题目是这样的,一个序列上有n个整数,现在你要取m个,且这m个数的任意两个不能相隔的太近,否则这样会太丑,现在问你最大能得到多大的和
Input
第一行三个数n,m,k,分别表示n个数,取m个,且m个中的任意两个位置差要大于等于K
接下来一行,有n个整数,表示序列上的每个数
Output
最大和
Sample Input
4 2 2
3 4 -5 1
Sample Output
5
Hint
数据范围:
n <= 10000,m <= 100,m <= n
答案保正小于 Maxlongint
Source
NOIdaokan
算法:DP
四道题里面唯一有点档次的题目了……
一开始想的是一个三重的循环,用f[i,j]表示前i个数里面选j个数能取得的最大和,然后从前面找个最优状态更新,结果果断超时,考完试下来之后才猛然发现,尼玛最优的状态不就是i-mm么(因为每次更新找的都是最优状态,因此最优状态只能是i-mm),这个坑爹的说,原来只要把最后的那层循环删掉就AC了的说。。。。
Time Limit:10000MS Memory Limit:65536K
Total Submit:23 Accepted:14
Description
香穗子遇到难题了.
题目是这样的,一个序列上有n个整数,现在你要取m个,且这m个数的任意两个不能相隔的太近,否则这样会太丑,现在问你最大能得到多大的和
Input
第一行三个数n,m,k,分别表示n个数,取m个,且m个中的任意两个位置差要大于等于K
接下来一行,有n个整数,表示序列上的每个数
Output
最大和
Sample Input
4 2 2
3 4 -5 1
Sample Output
5
Hint
数据范围:
n <= 10000,m <= 100,m <= n
答案保正小于 Maxlongint
Source
NOIdaokan
算法:DP
四道题里面唯一有点档次的题目了……
一开始想的是一个三重的循环,用f[i,j]表示前i个数里面选j个数能取得的最大和,然后从前面找个最优状态更新,结果果断超时,考完试下来之后才猛然发现,尼玛最优的状态不就是i-mm么(因为每次更新找的都是最优状态,因此最优状态只能是i-mm),这个坑爹的说,原来只要把最后的那层循环删掉就AC了的说。。。。
注意初始化,题目中有负值,因此fillchar为200,然后把前i项里面选0个的状态标记成0。
program p4;
const
maxn=10000;
maxm=100;
var
n,m,mm:longint;
a,maxx:array [0..maxn] of longint;
f:array [-maxn..maxn,0..maxm] of longint;
procedure init;
var
i:longint;
begin
readln(n,m,mm);
for i:=1 to n do read(a[i]);
end;
procedure main;
var
i,j,k:longint;
begin
fillchar(f,sizeof(f),200);
for i:=-maxn to n do f[i,0]:=0;
for i:=1 to n do
begin
for j:=1 to m do
begin
f[i,j]:=f[i-1,j];
if f[i-mm,j-1]+a[i]>f[i,j] then f[i,j]:=f[i-mm,j-1]+a[i];
end;
end;
end;
begin
assign(input,'4.in'); reset(input);
assign(output,'4.out'); rewrite(output);
init;
main;
writeln(f[n,m]);
close(input); close(output);
end.