Submit: 286 Solved: 209
Description
有3N个数,你需要选出一些数,首先保证任意长度为N的区间中选出的数的个数<=K个,其次要保证选出的数的个数最大。
Input
第一行两个整数N,K。
第二行有3N个整数。
Output
一行一个整数表示答案。
Sample Input
5 3
14 21 9 30 11 8 1 20 29 23 17 27 7 8 35
14 21 9 30 11 8 1 20 29 23 17 27 7 8 35
Sample Output
195
HINT
【数据范围】
N<=200,K<=10。
Source
数学问题 线性规划 费用流/单纯形
数据范围有些迷,要是时限大一倍也许可以DP卡过去?
正解是线性规划。
要求最大化$\sum x_i*c_i$,$c_i$是数的值,$x_i$为0或1,表示选或不选
限制条件是每连续的n个$ x_i $加起来<=K,并且每个$ x_i $满足 $ 0<=x_i<=1 $
可以将规划式差分后建费用流图(推荐 http://blog.csdn.net/jiangyuze831/article/details/44654723),或者直接跑单纯形。
zkw费用流20ms,吊打300+ms的单纯形
费用流:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int INF=0x3f3f3f3f; 9 const int mxn=10010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct edge{ 17 int v,nxt,f,w; 18 }e[mxn<<3]; 19 int hd[mxn],mct=1; 20 void add_edge(int u,int v,int f,int c){ 21 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=f;e[mct].w=c;hd[u]=mct;return; 22 } 23 void insert(int u,int v,int f,int c){ 24 add_edge(u,v,f,c);add_edge(v,u,0,-c);return; 25 } 26 int n,K; 27 int S,T,SS,TT; 28 int a[mxn]; 29 int cst=0; 30 queue<int>q; 31 int dis[mxn];bool inq[800]; 32 bool SPFA(){ 33 memset(inq,0,sizeof inq); 34 for(int i=SS;i<=TT;i++)dis[i]=INF; 35 q.push(SS);dis[SS]=0; 36 while(!q.empty()){ 37 int u=q.front();q.pop();inq[u]=0; 38 for(int i=hd[u],v;i;i=e[i].nxt){ 39 v=e[i].v; 40 if(e[i].f && dis[v]>dis[u]+e[i].w){ 41 dis[v]=dis[u]+e[i].w; 42 if(!inq[v]){ 43 inq[v]=1; 44 q.push(v); 45 } 46 } 47 } 48 } 49 return dis[TT]<INF; 50 } 51 int DFS(int u,int lim){ 52 if(u==TT){inq[u]=1;return lim;} 53 int f=0,tmp; 54 inq[u]=1; 55 for(int i=hd[u];i;i=e[i].nxt){ 56 int v=e[i].v; 57 if(!inq[v] && e[i].f && dis[u]+e[i].w==dis[v]){ 58 tmp=DFS(v,min(lim,e[i].f)); 59 cst+=tmp*e[i].w; 60 e[i].f-=tmp; e[i^1].f+=tmp; 61 f+=tmp; lim-=tmp; 62 if(!lim)return f; 63 } 64 } 65 return f; 66 } 67 int mcf(){ 68 int res=0; 69 while(SPFA()){ 70 inq[TT]=1; 71 while(inq[TT]){ 72 for(int i=SS;i<=TT;i++)inq[i]=0; 73 res+=DFS(SS,INF); 74 } 75 } 76 return res; 77 } 78 void solve(){ 79 mcf(); 80 printf("%d\n",-cst); 81 return; 82 } 83 int main(){ 84 int i,j; 85 n=read();K=read(); 86 SS=0;S=1;T=2*n+2;TT=T+1; 87 int ed=3*n; 88 for(i=1;i<=ed;i++)a[i]=read(); 89 insert(SS,S,K,0); 90 insert(T,TT,K,0); 91 for(i=1;i<=n;i++){ 92 insert(S,i+1,1,-a[i]); 93 insert(i+1,i+n+1,1,-a[i+n]); 94 insert(i+n+1,n+n+2,1,-a[i+n+n]); 95 } 96 for(i=2*n+1;i;i--)insert(i,i+1,INF,0); 97 // printf("fin\n"); 98 solve(); 99 return 0; 100 }