http://www.elijahqi.win/archives/2903
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
Sample Output
30
HINT
20%的数据:n<=10。
100%的数据:N<=1000,k,m<=100。Ci<=20000。
Source
By YM
考虑这题直接单纯形怎么做 直接列出式子即可 注意在矩阵的最后得添加一些限制使得x<=1
建图类似bzoj 志愿者招募
首先写出松弛型线性规划的这个式子
0≤xi≤1yi≥0x1+x2+...+xm+y1=kx2+x3+...+xm+1+y2=k...xn−m+1+xn−m+2+...+xn+yn−m+1=k
0
≤
x
i
≤
1
y
i
≥
0
x
1
+
x
2
+
.
.
.
+
x
m
+
y
1
=
k
x
2
+
x
3
+
.
.
.
+
x
m
+
1
+
y
2
=
k
.
.
.
x
n
−
m
+
1
+
x
n
−
m
+
2
+
.
.
.
+
x
n
+
y
n
−
m
+
1
=
k
然后在第一行之前添加0=0最后一行之后添加0=0 然后每行用i-(i-1)即可得到一个新的关系
x1+x2+...+xm+y1−k=0xm+1−x1+y2−y1=0xm+2−x2+y3−y2=0...xn−1−xn−m−1+yn−m−yn−m−1=0xn−xn−m+yn−m+1−yn−m=0−xn−m+1−xn−m+2−...−xn−yn−m+1+k=0
x
1
+
x
2
+
.
.
.
+
x
m
+
y
1
−
k
=
0
x
m
+
1
−
x
1
+
y
2
−
y
1
=
0
x
m
+
2
−
x
2
+
y
3
−
y
2
=
0
.
.
.
x
n
−
1
−
x
n
−
m
−
1
+
y
n
−
m
−
y
n
−
m
−
1
=
0
x
n
−
x
n
−
m
+
y
n
−
m
+
1
−
y
n
−
m
=
0
−
x
n
−
m
+
1
−
x
n
−
m
+
2
−
.
.
.
−
x
n
−
y
n
−
m
+
1
+
k
=
0
然后一个等式看作一个点 我们假设负数的为流出的正数为流入 同时一对正负恰好有对应关系
那么就针对x的这个限制做流量为1 然后费用为给定的边 然后同理y的这个边就做流量为inf 费用为0 最后我的1式 还有最后的那个式子分别连接下源点和汇点流量限制成k即可
因为网络流的类型太特殊了 多路增广并没有跑的比单路快..
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 1100
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
struct node{
int y,next,c,z;
}data[30000];
int num=1,h[N],cur[N],dis[N],T,n,m,k,ans,pre[N],path[N],in[N];bool flag[N];
inline void insert1(int x,int y,int z,int c){
//printf("%d %d %d %d\n",x,y,z,c);
data[++num].y=y;data[num].next=h[x];data[num].z=z;data[num].c=c;h[x]=num;
data[++num].y=x;data[num].next=h[y];data[num].z=0;data[num].c=-c;h[y]=num;
}
inline bool spfa(){
queue<int>q;q.push(0);for (int i=1;i<=T;++i) dis[i]=-inf;
memset(pre,-1,sizeof(pre));
memset(flag,0,sizeof(flag));flag[0]=0;dis[0]=0;
while(!q.empty()){
int x=q.front();q.pop();flag[x]=0;in[x]=0;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y,c=data[i].c,z=data[i].z;
if (dis[x]+c>dis[y]&&z){
pre[y]=x;path[y]=i;
dis[y]=dis[x]+c;if (!flag[y]) q.push(y),flag[y]=1;
}
}
}return dis[T]!=-inf;
}
inline int dfs(int x,int s){
if (x==T) {ans+=dis[T]*s;return s;}int ss=s;in[x]=1;
for (int &i=cur[x];i;i=data[i].next){
int y=data[i].y,z=data[i].z,c=data[i].c;
if (dis[x]+c==dis[y]&&z&&!in[y]){
int xx=dfs(y,min(z,s));if (!xx) dis[y]=-inf;
s-=xx;data[i].z-=xx;data[i^1].z+=xx;if(!s) return ss;
}
}return ss-s;
}
int main(){
freopen("bzoj1283.in","r",stdin);
n=read();m=read();k=read();T=n-m+3;
for (int i=1;i<=m;++i) insert1(i+1,1,1,read());
for (int i=m+1;i<=n-m;++i) insert1(i+1,i-m+1,1,read());
for (int i=n-m+1;i<=n;++i) insert1(T-1,i-m+1,1,read());
for (int i=2;i<=T-1;++i) insert1(i,i-1,inf,0);
insert1(1,T,k,0);insert1(0,T-1,k,0);
/* while(spfa()){
int minn=inf,now=T;
while(now) minn=min(minn,data[path[now]].z),now=pre[now];ans+=minn*dis[T];now=T;
while(now) data[path[now]].z-=minn,data[path[now]^1].z+=minn,now=pre[now];
}*/
while(spfa()) memcpy(cur,h,sizeof(h)),dfs(0,inf);
printf("%d\n",ans);
return 0;
}