• Aizu Aoj 2266 (费用流


    题目(原文是日语):

      Google Code Jam区域赛上,坐在右前方的男人ID叫lyrically。东京大学时代的记忆中,记得有个朋友也用类似的ID。不过我的朋友都是萌妹子,我记忆中的 lyrically不仅算法扎实,封装也很强,能一下子给出问题的正解。比如,对我们写得不好的程序也能优化到AC的程度。她说,程序优化时,对缓存池的 利用特别重要。

    那么问题来了,现在请你优化下面的缓存池模型:

    有M个桶,N个球,球编号为1到N,每个球都有重量w_i。然后给出一个长K的数列,数列由球的编号构成。开始的时候,桶都是空的。接着我们从前往后从数列中取出一个数a_j,执行如下操作:

    如果球a_j已经存在于某一个桶中,那么什么也不干,花费为0,继续。

    如果任何桶中都没有a_j,那么找一个桶放a_j,如果该桶里还有球,那么取出原来的球,将a_j放进去。这种操作的花费是a_j的重量w_a_j,与桶以及原来的球没关系。

    求最小花费?

    题目数据第一行是M N K,接着N行权重,K行编号。

    思路:首先这是《挑战程序设计》的费用流部分的练习题。。那么就要从费用流的方向来考虑。我们使用桶子的时候,每个时候一定有一个桶子是要用来装新球的,也就是说这个桶子不是保留的桶子,同时其他桶子可以是空桶,也可以装了东西。之后可能会用到之前的球来减少花费。那么我们只需要考虑最有效的保留方式能节省多少钱。同时最多有m-1个桶是保留的,保留多久呢?保留到下一次遇到相同的球。那么如果选择保留这个桶,这个桶在这个区间内都是不可用的。仔细想想,这不就是书上的例题最大权区间选择吗!(poj 3680).那么问题就是,如何选择最多m-1个相交区间,使得权值和最大。

    题目翻译来自:http://www.hankcs.com/program/algorithm/aoj-2266-cache-strategy.html

     

    /*
    * @author:  Cwind
    */
    
    ///#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    
    using namespace std;
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-10)
    #define INF (1000000300)
    #define clr(x) memset((x),0,sizeof (x))
    #define cp(a,b) memcpy((a),(b),sizeof (b))
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> P;
    typedef pair<ll,int> D;
    
    
    const int MAXV=1e4+300;
    int V;
    const int s=MAXV-1,t=MAXV-2;
    struct EDGE{
        int to,cap,cost,next;
    }ES[MAXV*10];
    int eh;
    int h[MAXV];
    int dis[MAXV];
    int prevv[MAXV],preve[MAXV];
    int head[MAXV];
    void addedge(int from,int to,int cap,int cost){
        ES[eh].to=to;ES[eh].cap=cap;ES[eh].cost=cost;
        ES[eh].next=head[from];head[from]=eh++;
        ES[eh].to=from;ES[eh].cap=0;ES[eh].cost=-cost;
        ES[eh].next=head[to];head[to]=eh++;
    }
    bool inq[MAXV];
    ll min_cost_flow(int s,int t,int f){
        V=MAXV;//default V size maxed
        ll res=0;
        memset(h,0,sizeof h);
        queue<P> Q;////spfa计算势h
        fill(dis,dis+V,INF);
        dis[s]=0;
        Q.push(P(0,s));
        inq[s]=1;
        while(!Q.empty()){
            P p=Q.front();Q.pop();
            int v=p.se;
            inq[v]=0;
            for(int i=head[v];i!=-1;i=ES[i].next){
                EDGE &e=ES[i];
                if(e.cap>0&&dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]){
                    dis[e.to]=dis[v]+e.cost +h[v]-h[e.to];
                    prevv[e.to]=v;
                    preve[e.to]=i;
                    if(!inq[e.to]) Q.push(P(dis[e.to],e.to)),inq[e.to]=1;
                }
            }
        }
        for(int v=0;v<V;v++)
            h[v]+=dis[v];
        while(f>0){
            priority_queue<P,vector<P> ,greater<P> >Q;////Dijkstra计算势h
            fill(dis,dis+V,INF);
            dis[s]=0;
            Q.push(P(0,s));
            while(!Q.empty()){
                P p=Q.top();Q.pop();
                int v=p.se;
                if(dis[v]<p.fs) continue;
                for(int i=head[v];i!=-1;i=ES[i].next){
                    EDGE &e=ES[i];
                    if(e.cap>0&&dis[e.to]>dis[v]+e.cost+h[v]-h[e.to]){
                        dis[e.to]=dis[v]+e.cost +h[v]-h[e.to];
                        prevv[e.to]=v;
                        preve[e.to]=i;
                        Q.push(P(dis[e.to],e.to));
                    }
                }
            }
            if(dis[t]==INF) return -1;
            for(int v=0;v<V;v++) h[v]+=dis[v];
            int d=f;
            for(int v=t;v!=s;v=prevv[v])
                d=min(d,ES[preve[v]].cap);
            f-=d;
            res+=d*h[t];
            for(int v=t;v!=s;v=prevv[v]){
                EDGE &e=ES[preve[v]];
                e.cap-=d;
                ES[preve[v]^1].cap+=d;
            }
        }
        return res;
    }
    void clear_G(){
        eh=0;
        memset(head,-1,sizeof head);
    }
    
    const int maxn=1e4+300;
    int M,N,K;
    int a[maxn],w[maxn];
    int last[maxn];
    int tol;
    int hh;
    void build(){
        for(int i=1;i<hh;i++){
            tol+=w[a[i]];
            if(last[a[i]])
                addedge(last[a[i]],i-1,1,-w[a[i]]);
            last[a[i]]=i;
        }
        for(int i=1;i<hh-1;i++)
            addedge(i,i+1,INF,0);
    }
    int main(){
        freopen("/home/slyfc/CppFiles/in","r",stdin);
        //freopen("/home/slyfc/CppFiles/out","w",stdout);
        clear_G();
        cin>>M>>N>>K;
        for(int i=1;i<=N;i++)
            scanf("%d",&w[i]);
        for(int i=1;i<=K;i++)
            scanf("%d",&a[i]);
        hh=unique(a+1,a+K+1)-a;
        build();
        int ans=min_cost_flow(1,hh-1,M-1);
        cout<<tol+ans<<endl;
        return 0;    
    }
    View Code

     

     

  • 相关阅读:
    HDFS小文件处理——Mapper处理
    HDFS 小文件处理——应用程序实现
    kafka的环境搭建
    Storm集群的搭建
    Pig简单入门
    HBase学习笔记
    HBase的Shell操作
    面试必备2014
    常用SQL Server分页方式
    C# DES 加密解密
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4942180.html
Copyright © 2020-2023  润新知