zoukankan      html  css  js  c++  java
  • 汕头市队赛 SRM16 T2

    描述

          猫和老鼠,看过吧?猫来了,老鼠要躲进洞里。在一条数轴上,一共有n个洞,位置分别在xi,能容纳vi只老鼠。一共有m只老鼠位置分别在Xi,要躲进洞里,问所有老鼠跑进洞里的距离总和最小是多少。

    输入格式

          两个用空格隔开的整数m和n。

          这一行m个数字分别表示老鼠的位置

          接下来n行每行两个数字分别表示洞的位置和容纳量

    输出格式

          一个整数,表示最小的距离总和。(如果无解,输出-1)

    样例输入

    4 5
    6 2 8 9
    3 6
    2 1
    3 6
    4 7
    4 7

    样例输出

    11
    ——————————————————————————
     n <= 500, m <= 500 的时候可以写费用流 但是要比较好的建图方式
    nm的建图肯定要挂
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int M=2e3+7,inf=0x3f3f3f3f;
    const LL mx=1e15;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9') {ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,q[M],vis[M];
    int N,S,T;
    LL ans,d[M];
    struct node{int to,next,flow;LL cost;}e[M*M];
    int first[M],cnt=1,cur[M];
    void ins(int a,int b,int flow,LL cost){e[++cnt]=(node){b,first[a],flow,cost}; first[a]=cnt;}
    void insert(int a,int b,int flow,LL cost){ins(a,b,flow,cost); ins(b,a,0,-cost);}
    bool spfa(){
        for(int i=S;i<=T;i++) d[i]=mx;
        int head=0,tail=1;
        q[0]=T; vis[T]=1; d[T]=0;
        while(head!=tail){
             int x=q[head++]; if(head>M) head=0;
             for(int i=first[x];i;i=e[i].next){
                 int now=e[i].to;
                if(e[i^1].flow&&d[x]+e[i^1].cost<d[now]){
                    d[now]=d[x]+e[i^1].cost;
                    if(!vis[now]){
                        if(d[now]<d[q[head]]){head--; if(head<0) head=M; q[head]=now;}
                        else{q[tail++]=now; if(tail>M) tail=0;}
                        vis[now]=1;
                    }
                }            
             }
             vis[x]=0;
         }
        return d[S]<mx;
    }
    int dfs(int x,int a){
        if(x==T||a==0)return a;
        vis[x]=1;
        int flow=0,f;
        for(int& i=cur[x];i;i=e[i].next){
            int now=e[i].to;
            if(!vis[now]&&d[x]==e[i].cost+d[now]&&(f=dfs(now,min(a,e[i].flow)))>0){
                   e[i].flow-=f; e[i^1].flow+=f;
                ans+=e[i].cost*f; flow+=f;
                  a-=f;if(a==0)break;
            }
          }
        vis[x]=0;
        return flow;
    }
    int x[M];
    LL sum;
    struct pos{int y,k;}qq[M];
    bool cmp(pos a,pos b){return a.y<b.y;}
    int main()
    {
        n=read(); m=read();
        S=0; T=n+m+1;
        for(int i=1;i<=n;i++) x[i]=read(),insert(S,i,1,0);
        for(int i=1;i<=m;i++) qq[i].y=read(),qq[i].k=read(),sum+=qq[i].k;
        if(sum<n){printf("-1
    "); return 0;}
        sort(qq+1,qq+1+m,cmp);
        for(int i=1;i<=m;i++) insert(i+n,T,qq[i].k,0);
        for(int i=1;i<=m;i++){
            if(i>1) insert(i+n,i+n-1,inf,qq[i].y-qq[i-1].y);
            if(i<m) insert(i+n,i+n+1,inf,qq[i+1].y-qq[i].y);
        }
        for(int i=1;i<=n;i++){
            int k1=1; while(qq[k1+1].y<=x[i]&&k1<m) k1++;
            int k2=m; while(qq[k2-1].y>=x[i]&&k2>1) k2--;
            if(qq[k1].y<=x[i]) insert(i,k1+n,1,x[i]-qq[k1].y);
            if(qq[k2].y>=x[i]) insert(i,k2+n,1,qq[k2].y-x[i]);
        }
        while(spfa()){for(int i=0;i<=T;i++) cur[i]=first[i]; dfs(S,inf);}
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    n <= 5000, m <= 5000 的时候就需要dp了

    先将洞和老鼠按位置从小到大排一波序

    因为老鼠选的洞必然是单调递增的 我们可以考虑dp

    f【i】【j】表示前i个洞选j只老鼠

    转移方程 f【i】【j】=f【i-1】【k】+(k+1到j 的距离

    然后发现是三方的写法 然后就后面可以用单调队列优化dp降一波复杂度

    然后就是n方写法了

    这里我们每次可以算一下每只老鼠到 第i个洞的 前缀

    队列里扔的就是f【j】+(前缀数组)s【j】就好啦

    f【i】=q【l】+s【i】就好辣

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int M=5e3+7;
    const LL inf=1e15;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9') {ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int l,r,n,m,x[M];
    struct pos{int y,k;}e[M];
    bool cmp(pos a,pos b){return a.y<b.y;}
    LL sum,f[M],s[M];
    LL pabs(LL x){return x>=0?x:-x;}
    struct node{LL v; int pos;}q[M];
    int main()
    {
        n=read(); m=read();
        for(int i=1;i<=n;i++) x[i]=read();
        for(int i=1;i<=m;i++) e[i].y=read(),e[i].k=read(),sum+=e[i].k;
        if(sum<n){printf("-1
    "); return 0;}
        sort(x+1,x+1+n);
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=n;i++) f[i]=inf;
        for(int i=1;i<=m;i++){
            l=1; r=0;
            for(int j=1;j<=n;j++) s[j]=s[j-1]+pabs(x[j]-e[i].y);
            for(int j=0;j<=n;j++){
                while(l<=r&&q[r].v>=f[j]-s[j]) r--;
                while(l<=r&&(j-q[l].pos)>e[i].k) l++;
                q[++r].v=f[j]-s[j]; q[r].pos=j;
                f[j]=q[l].v+s[j];
            }
        }printf("%lld
    ",f[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    05---二叉树---20195106023---王亚威.c
    05---二叉树---20195106043---方传祥.c
    05---二叉树---20195106006---陈辉.c
    05---二叉树---20195106064---陈昕.c
    05---二叉树---20195106100---李遂勋.c
    2020下---3D建模---作业---blender
    nothing provides python(abi) = 3.8 needed by VirtualBox-6.1-6.1.16_140961_fedora32-1.x86_64
    el-table、pl-table(u-table)、ux-grid解决表格问题的实例(大数据量)
    1800*1【Codeforces Round #665 (Div. 2) D】Maximum Distributed Tree
    【Educational Codeforces Round 97 (Rated for Div. 2) C】Chef Monocarp
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7440311.html
Copyright © 2011-2022 走看看