zoukankan      html  css  js  c++  java
  • bzoj1930

    1930: [Shoi2003]pacman 吃豆豆

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1923  Solved: 435
    [Submit][Status][Discuss]

    Description

    两个PACMAN吃豆豆。一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方。PACMAN走到豆豆处就会吃掉它。PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行走的路线不可以相交。 请你帮这两个PACMAN计算一下,他们俩加起来最多能吃掉多少豆豆。

    Input

    第一行为一个整数N,表示豆豆的数目。 接下来 N 行,每行一对正整数,表示第i个豆豆的坐标。任意两个豆豆的坐标都不会重合。

    Output

    仅有一行包含一个整数,即两个PACMAN加起来最多能吃掉的豆豆数量

    Sample Input

    8

    8 1

    1 5

    5 7

    2 2

    7 8

    4 6

    3 3

    6 4

    Sample Output

    7

    HINT

     

    N < = 2000

    Source

    666 卡内存,zky大神只用了2000kb

    很容易想出这是个最大费用流。但是很明显,2000*2000的边很容易tle,那么我们要进行剪枝。如果a->b,b->c,那么a->c是没有必要的。

    但是还卡空间,因此我们可以用short。。。 连边:s:原点 ss:原点拆开的点,t:汇点

    link(s,ss,f=2,c=0) for each i link(ss,i,f=2,c=0) link(i+n(拆点),t,f=2,c=0)

    每个点和可以到达的点:link(i+n,j,f=1,c=1) link(i+n,j,f=1,c=1) 并且我们先按x排序,从x小到大枚举,如果当前的y比之前最小值要大,那么肯定之前连过,不用连了。

    #include<bits/stdc++.h>  
    using namespace std;
    #define inf (1<<30)
    #define N 2010
    struct edge
    {
        short f,c,to;
        int nxt;
    }e[4500010];
    struct data
    {
        int x,y;
    }x[4010];
    int cnt=1,s,t,ss,n;
    int pree[4010],prev[4010],dist[4010],head[4010];
    short q[4200010];
    inline bool cp(data x,data y)
    {
        if(x.x!=y.x) return x.x<y.x;
        return x.y<y.y;
    }
    inline int min(int x,int y)
    {
        return x<y?x:y;
    }
    inline void link(int u,int v,int f,int c)
    {
        e[++cnt].nxt=head[u];
        head[u]=cnt;
        e[cnt].to=v;
        e[cnt].f=f;
        e[cnt].c=c;
    }
    inline void ins(int u,int v,int c,int f)
    {
        link(u,v,f,c);  link(v,u,0,-c);
    }
    inline bool spfa()
    {
        memset(dist,-1,sizeof(dist));
        int l=1,r=0;
        q[++r]=s; dist[s]=0;
        while(l<=r)
        {
            int u=q[l++]; 
            for(int i=head[u];i;i=e[i].nxt) if(e[i].f&&dist[e[i].to]<dist[u]+e[i].c)
            {
                prev[e[i].to]=u;
                pree[e[i].to]=i;
                dist[e[i].to]=dist[u]+e[i].c;
                q[++r]=e[i].to;
            }
        }
        return dist[t]!=-1;
    }
    inline int flow()
    {
        int u=t,delta=inf;
        while(u!=s)
        {
            delta=min(delta,e[pree[u]].f);
            u=prev[u];
        }
        u=t;
        while(u!=s)
        {
            e[pree[u]].f-=delta;
            e[pree[u]^1].f+=delta;
            u=prev[u];
        }
        return dist[t]*delta;
    }
    inline void MinCostFlow()
    {
        int ans=0,cur=0;
        while(spfa())
        {
            cur+=flow();
            if(cur>ans) ans=cur;
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        scanf("%d",&n); s=2*n+1; t=2*n+2; ss=s+2; 
        for(int i=1;i<=n;i++) scanf("%d%d",&x[i].x,&x[i].y);
        ins(s,ss,0,2);
        for(int i=1;i<=n;i++)
        {
            ins(ss,i,0,2);
            ins(i+n,t,0,2);
        } 
        sort(x+1,x+n+1,cp);
        for(int i=1;i<=n;i++)
        {
            ins(i,i+n,1,1);
            ins(i,i+n,0,1);
            int top=inf;
            for(int j=i+1;j<=n;j++)
                if(x[j].y<top&&x[i].y<=x[j].y) 
                    ins(i+n,j,0,2),top=x[j].y;
        }
        MinCostFlow();
        return 0;
    } 
    View Code
  • 相关阅读:
    CSS居中方法搜集
    函数表达式与函数声明的一点区别
    z-index 解析
    Android EditText的输入监听,输入字符的动态获取
    dispatchkeyevent的调用机制
    自定义带有图片的PreferenceActivity
    declare-styleable:自定义控件的属性
    在fragment中调用SharedPreferences
    使用Preference保存设置
    getSharedPreferences()与getSharedPreferences()与getDefaultSharedPreferences()的区别
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6360019.html
Copyright © 2011-2022 走看看