Bzoj3550 [ONTAK2010]Vacation
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 }
单纯形:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 using namespace std; 7 const double eps=1e-9; 8 const int mxn=1315; 9 int read(){ 10 int x=0,f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 double a[mxn][mxn]; 16 int idx[mxn],idy[mxn]; 17 int n,m,K; 18 int st[mxn],top=0; 19 void Pivot(int x,int y){ 20 swap(idy[x],idx[y]); 21 double tmp=a[x][y];a[x][y]=1/a[x][y]; 22 int i,j;top=0; 23 for(i=0;i<=n;i++)if(y!=i)a[x][i]/=tmp; 24 for(i=0;i<=n;i++)if(y!=i && fabs(a[x][i])>eps)st[++top]=i; 25 for(i=0;i<=m;i++){ 26 if((i==x)|| fabs(a[i][y])<eps)continue; 27 for(j=1;j<=top;j++)a[i][st[j]]-=a[x][st[j]]*a[i][y]; 28 a[i][y]=-a[i][y]/tmp; 29 } 30 return; 31 } 32 void Simplex(){ 33 int i,j; 34 while(1){ 35 int x=0,y=0;double mn=1e16; 36 for(i=1;i<=n;i++)if(a[0][i]>eps){y=i;break;} 37 if(!y)break; 38 for(i=1;i<=m;i++){ 39 if(a[i][y]>eps && (a[i][0]/a[i][y]<mn)){ 40 mn=a[i][0]/a[i][y]; 41 x=i; 42 } 43 } 44 Pivot(x,y); 45 } 46 return; 47 } 48 int main(){ 49 int i,j; 50 n=read();m=0;K=read(); 51 int ed=n*3; 52 for(i=1;i<=ed;i++)a[0][i]=read(); 53 for(i=1;i+n-1<=ed;i++){ 54 m++;a[m][0]=K; 55 for(j=0;j<n;j++) 56 a[m][i+j]=1; 57 } 58 for(i=1;i<=ed;i++){ 59 m++;a[m][0]=1;a[m][i]=1; 60 } 61 for(i=1;i<=ed;i++)idx[i]=i; 62 for(i=1;i<=m;i++)idy[i]=i+ed; 63 n=ed;// 64 Simplex(); 65 printf("%.0f\n",-a[0][0]+0.3); 66 return 0; 67 }
本文为博主原创文章,转载请注明出处。