1283: 序列
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 200 Solved: 114
[ Submit][ Status][ Discuss]
Description
给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大。
Input
第1行三个数N,m,k。 接下来N行,每行一个字符串表示Ci。
Output
最大和。
Sample Input
10 5 3
4 4 4 6 6 6 6 6 4 4
4 4 4 6 6 6 6 6 4 4
Sample Output
30
HINT
20%的数据:n<=10。
100%的数据:N<=1000,k,m<=100。Ci<=20000。
解题思路:同NOI2008招募。此处是最大费用最大流
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 1000000000
#define pa pair<int,int>
#define ll long long
#define mod 1000000007
using
namespace
std
;
int
read
(
)
{
int
x
=
0
,
f
=
1
;
char
ch
=
getchar
(
)
;
while
(
ch
<
'0'
||
ch
>
'9'
)
{
if
(
ch
==
'-'
)
f
=
-
1
;
ch
=
getchar
(
)
;
}
while
(
ch
>=
'0'
&&
ch
<=
'9'
)
{
x
=
x
*
10
+
ch
-
'0'
;
ch
=
getchar
(
)
;
}
return
x
*
f
;
}
int
n
,
m
,
cnt
=
1
,
K
,
T
,
ans
;
int
a
[
2005
]
,
q
[
2005
]
,
last
[
2005
]
,
dis
[
2005
]
;
bool
inq
[
2005
]
,
mark
[
2005
]
;
struct
edge
{
int
to
,
next
,
v
,
c
;
}
e
[
10005
]
;
void
insert
(
int
u
,
int
v
,
int
w
,
int
c
)
{
e
[
++
cnt
]
.
to
=
v
;
e
[
cnt
]
.
next
=
last
[
u
]
;
last
[
u
]
=
cnt
;
e
[
cnt
]
.
v
=
w
;
e
[
cnt
]
.
c
=
c
;
e
[
++
cnt
]
.
to
=
u
;
e
[
cnt
]
.
next
=
last
[
v
]
;
last
[
v
]
=
cnt
;
e
[
cnt
]
.
v
=
0
;
e
[
cnt
]
.
c
=
-
c
;
}
bool
spfa
(
)
{
int
head
=
0
,
tail
=
1
;
memset
(
dis
,
-
1
,
sizeof
(
dis
)
)
;
q
[
0
]
=
T
;
dis
[
T
]
=
0
;
while
(
head
!=
tail
)
{
int
now
=
q
[
head
]
;
head
++
;
inq
[
now
]
=
0
;
if
(
head
==
2005
)
head
=
0
;
for
(
int
i
=
last
[
now
]
;
i
;
i
=
e
[
i
]
.
next
)
if
(
dis
[
now
]
+
e
[
i
^
1
]
.
c
>
dis
[
e
[
i
]
.
to
]
&&
e
[
i
^
1
]
.
v
)
{
dis
[
e
[
i
]
.
to
]
=
dis
[
now
]
+
e
[
i
^
1
]
.
c
;
if
(
!
inq
[
e
[
i
]
.
to
]
)
{
inq
[
e
[
i
]
.
to
]
=
1
;
q
[
tail
++
]
=
e
[
i
]
.
to
;
if
(
tail
==
2005
)
tail
=
0
;
}
}
}
return
dis
[
0
]
!=
-
1
;
}
void
build
(
)
{
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
if
(
i
<=
m
)
insert
(
n
+
2
,
i
,
1
,
a
[
i
]
)
;
else
if
(
i
<=
n
-
m
)
insert
(
i
-
m
,
i
,
1
,
a
[
i
]
)
;
else
insert
(
i
-
m
,
n
+
1
,
1
,
a
[
i
]
)
;
}
for
(
int
i
=
1
;
i
<=
n
-
m
+
1
;
i
++
)
insert
(
i
,
i
+
1
,
K
,
0
)
;
insert
(
0
,
n
+
2
,
K
,
0
)
;
insert
(
n
+
1
,
T
,
K
,
0
)
;
}
int
dfs
(
int
x
,
int
f
)
{
mark
[
x
]
=
1
;
if
(
x
==
T
)
return
f
;
int
w
,
used
=
0
;
for
(
int
i
=
last
[
x
]
;
i
;
i
=
e
[
i
]
.
next
)
if
(
!
mark
[
e
[
i
]
.
to
]
&&
e
[
i
]
.
v
&&
dis
[
x
]
-
e
[
i
]
.
c
==
dis
[
e
[
i
]
.
to
]
)
{
w
=
dfs
(
e
[
i
]
.
to
,
min
(
e
[
i
]
.
v
,
f
-
used
)
)
;
e
[
i
]
.
v
-=
w
;
e
[
i
^
1
]
.
v
+=
w
;
ans
+=
w
*
e
[
i
]
.
c
;
used
+=
w
;
if
(
used
==
f
)
return
f
;
}
return
used
;
}
void
zkw
(
)
{
int
flow
=
0
;
while
(
spfa
(
)
)
{
memset
(
mark
,
0
,
sizeof
(
mark
)
)
;
mark
[
T
]
=
1
;
while
(
mark
[
T
]
)
{
mark
[
T
]
=
0
;
flow
+=
dfs
(
0
,
inf
)
;
}
}
}
int
main
(
)
{
n
=
read
(
)
;
m
=
read
(
)
;
K
=
read
(
)
;
T
=
n
;
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
a
[
i
]
=
read
(
)
;
build
(
)
;
zkw
(
)
;
printf
(
"%d\n"
,
ans
)
;
return
0
;
}