zoukankan      html  css  js  c++  java
  • BZOJ 1283: 序列

    Description

    在长度为 (n)的序列中选出一个子序列,满足任意长度为 (m) 的子串中出现的数字不超过 (k) 个,求最大价值 (n leqslant 10^3, m,kleqslant 10^2).

    Solution

    费用流.

    费用流建模的一个思路,任意 (m) 长序列满足条件,那么就让一个点往他后面的第(m)个点连边,容量为(1),费用为这个点的权值,从源点再连出来一条容量为(k)的边即可,中间所有相邻的先全部连容量无穷没有费用的边,让图连通,并且这些边不可能而被割掉.

    还有一种思路是从线性规划来建.
    我们可以列出一堆式子来,通过添加辅助变量$y_i$
    (a_1+a_2+...+a_m+y_1=k)
    (a_2+a_3+...+a_{m+1}+y_2=k)
    (...)
    (a_{n-m+1}+a_{n-m+2}+...a_n+y_{n-m+1}=k)
    然后用下面的式子去减上面的式子
    (a_1+a_2+...+a_m+y_1=k)
    (a_{m+1}+y_2=a_1+y_1)
    (...)
    (a_{n-m}+y_{n-m+1}=a_n+y_n)
    (a_{n-m+1}+...+a_n+y_{n-m+1}=k)
    然后将等式看做节点,等式两边分别表示入流和出流,变量看做是边的流量,建出来的图是一样的.

    Code

    /**************************************************************
        Problem: 1283
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:320 ms
        Memory:1512 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    #define debug(a) cout<<#a<<"="<<a<<" "
    const int N = 2005;
    const int INF = 0x3fffffff;
     
    inline int in(int x=0) { scanf("%d",&x);return x; }
     
     
    int n,m,k;
    int w[N];
     
    struct Network {
        int e;
        struct Edge { int fr,to,fl,w; }edge[N*5];
        vector< int > g[N];
        int a[N],p[N],b[N],d[N];
        int s,t,flow,cost;
         
        void AddEdge(int fr,int to,int fl,int w) {
            g[fr].push_back(e);
            edge[e++]=(Edge){ fr,to,fl,w };
            g[to].push_back(e);
            edge[e++]=(Edge){ to,fr,0,-w };
        }
        int SPFA(int s,int t) {
            queue< int > q;q.push(s);
            memset(b,0,sizeof(b)),memset(d,0x80,sizeof(d));
            a[s]=INF,d[s]=0;
            for(int x;!q.empty();) {
                x=q.front(),q.pop(),b[x]=0;
    //          debug(x)<<endl;
                for(int i=0,v;i<(int)g[x].size();i++)
                    if(edge[g[x][i]].fl>0 && d[x]+edge[g[x][i]].w>d[v=edge[g[x][i]].to]) {
                        d[v]=d[x]+edge[g[x][i]].w,p[v]=g[x][i],a[v]=min(a[x],edge[g[x][i]].fl);
    //                  debug(d[v]),debug(a[v])<<endl;
                        if(!b[v]) q.push(v),b[v]=1;
                    }
            }
            if(d[t]<0) return 0;
    //      debug(d[t])<<endl;
            cost+=a[t]*d[t],flow+=a[t];
            for(int x=t;x!=s;x=edge[p[x]].fr) {
                edge[p[x]].fl-=a[t];
                edge[p[x]^1].fl+=a[t];
            }
            return 1;
        }
        void Build() {
            s=0,t=n+1;
            AddEdge(s,1,k,0),AddEdge(n,t,INF,0);
            for(int i=1;i<=n;i++) {
                if(i!=n) AddEdge(i,i+1,INF,0);
                if(i+m<=n) AddEdge(i,i+m,1,w[i]);
                else AddEdge(i,t,1,w[i]);
            }
        }
        void Work() {
            Build();
            while(SPFA(s,t));
            printf("%d
    ",cost);
        }
    }py;
     
    int main() {
        n=in(),m=in(),k=in();
        for(int i=1;i<=n;i++) w[i]=in();
        py.Work();
        return 0;
    }
    /*
    10 5 3
    4 4 4 6 6 6 6 6 4 4
    */
    
  • 相关阅读:
    HDU 1203 I NEED A OFFER!(0-1背包)
    poj3624 Charm Bracelet(0-1背包 滚动数组)
    Contest1803
    2019 Multi-University Training Contest 3
    Circle and Points
    分治算法应用-最近点对的最小距离-hdu 1007 Quoit Design
    2019年第二阶段我要变强个人训练赛第十七场
    2019牛客暑期多校训练营(第四场)
    2019牛客暑期多校训练营(第三场)
    2019 Multi-University Training Contest 2
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6327361.html
Copyright © 2011-2022 走看看