题目链接:学姐的逛街计划
描述
doc 最近太忙了, 每天都有课. 这不怕, doc 可以请假不去上课.
偏偏学校又有规定, 任意连续 n 天中, 不得请假超过 k 天.
doc 很忧伤, 因为他还要陪学姐去逛街呢.
后来, doc发现, 如果自己哪一天智商更高一些, 陪学姐逛街会得到更多的好感度.
现在 doc 决定做一个实验来验证自己的猜想, 他拜托 小岛 预测出了 自己 未来 3n 天中, 每一天的智商.
doc 希望在之后的 3n 天中选出一些日子来陪学姐逛街, 要求在不违反校规的情况下, 陪学姐逛街的日子自己智商的总和最大.
可是, 究竟这个和最大能是多少呢?
格式
输入格式
第一行给出两个整数, n 和 k, 表示我们需要设计之后 3n 天的逛街计划, 且任意连续 n 天中不能请假超过 k 天.
第二行给出 3n 个整数, 依次表示 doc 每一天的智商有多少. 所有数据均为64位无符号整数
输出格式
输出只有一个整数, 表示可以取到的最大智商和.
样例1
样例输入1
5 3
14 21 9 30 11 8 1 20 29 23 17 27 7 8 35
Copy
样例输出1
195
Copy
限制
对于 20% 的数据, 1 <= n <= 12 , k = 3.
对于 70% 的数据, 1 <= n <= 40 .
对于 100% 的数据, 1 <= n <= 200 , 1 <= k <= 10.
bzoj原题。
我们通过问题转换:原问题等价于我们选k次,每次任意n个数当中只能选一个数字。
直接最大费用流。
我们直接让流量最大为k即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N=610,M=1e5+10;
int n,m,k,s,t,d[N],v[N],e[N],a[N];
int head[N],nex[M],to[M],w[M],flow[M],tot=1;
inline void ade(int a,int b,int c,int d){
to[++tot]=b; nex[tot]=head[a]; w[tot]=d; flow[tot]=c; head[a]=tot;
}
inline void add(int a,int b,int c,int d){ade(a,b,c,d); ade(b,a,0,-d);}
inline int spfa(){
memset(d,0xcf,sizeof d); d[s]=0; int vis[N]={0}; vis[s]=1;
queue<int> q; q.push(s);
while(q.size()){
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u];i;i=nex[i]){
if(flow[i]&&d[to[i]]<d[u]+w[i]){
d[to[i]]=d[u]+w[i];
v[to[i]]=u; e[to[i]]=i;
if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;
}
}
}
return d[t]!=0xcfcfcfcf;
}
int EK(){
int res=0;
while(spfa()){
int mi=inf;
for(int i=t;i!=s;i=v[i]) mi=min(flow[e[i]],mi);
for(int i=t;i!=s;i=v[i]) flow[e[i]]-=mi,flow[e[i]^1]+=mi;
res+=d[t]*mi;
}
return res;
}
signed main(){
cin>>n>>k; m=n*3; t=m+1;
for(int i=1;i<=m;i++) cin>>a[i];
add(s,1,k,0); add(m,t,k,0);
for(int i=1;i<m;i++) add(i,i+1,k,0);
for(int i=1;i<=m-n;i++) add(i,i+n,1,a[i]);
for(int i=m-n+1;i<=m;i++) add(i,t,1,a[i]);
cout<<EK()<<endl;
return 0;
}