Bzoj3550 [ONTAK2010]Vacation

Time Limit: 10 Sec  Memory Limit: 96 MB
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

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 }
View Code

单纯形:

 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 }
View Code

 

posted @ 2017-05-26 15:36  SilverNebula  阅读(270)  评论(0编辑  收藏  举报
AmazingCounters.com