BZOJ1930: [Shoi2003]pacman 吃豆豆

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

/**************************************************************

    Problem: 1930

    User: ictsing

    Language: C++

    Result: Accepted

    Time:244 ms

    Memory:42388 kb

****************************************************************/

 

//BZOJ1930 [Shoi2003]pacman 吃豆豆

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <queue>

#include <cstring>

using namespace std;

const int inf = 1e9;

int s=0,t;

int s1,t1;

const int mt = 4000+5;

int fr[2100000],to[2100000],nxt[2100000],cap[2100000],cost[2100000],adj[mt],cur[mt];

bool inq[mt];

int dis[mt],lev[mt];

int ecnt=1;

struct node

{

    int x,y;

}a[mt>>1];

bool operator < (node a,node b)

{

    if(a.x==b.x) return a.y<b.y;

    return a.x<b.x;

}

int ans=0;

queue<int>q;

int read()

{

    int num=0,flag=1;

    char ch;

    do{

        ch=getchar();

        if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

        num=num*10+ch-'0';

        ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

void adde(int u,int v,int cc,int ccc)

{

    ecnt++,fr[ecnt]=u,to[ecnt]=v,nxt[ecnt]=adj[u],cap[ecnt]=cc,cost[ecnt]=ccc,adj[u]=ecnt;

    ecnt++,fr[ecnt]=v,to[ecnt]=u,nxt[ecnt]=adj[v],cap[ecnt]=0,cost[ecnt]=-ccc,adj[v]=ecnt;

}

bool spfa()

{

    while(!q.empty()) q.pop();

    for(int i=s;i<=t;i++) dis[i]=inf,inq[i]=0;

    q.push(s),dis[s]=0,inq[s]=1;

    while(!q.empty())

    {

        int u=q.front();q.pop();inq[u]=0;

        for(int i=adj[u];i;i=nxt[i])

        {

            int v=to[i];

            if(dis[v]>dis[u]+cost[i]&&cap[i])

            {

                dis[v]=dis[u]+cost[i];cur[v]=i;

                if(!inq[v]) inq[v]=1,q.push(v); 

            }

        }

    }

    return dis[t]!=inf;

}

void mcf()

{

    while(spfa())

    {

        int tmp=inf;

        for(int i=cur[t];i;i=cur[fr[i]]) tmp=min(tmp,cap[i]);

        ans+=dis[t]*tmp;

        for(int i=cur[t];i;i=cur[fr[i]]) cap[i]-=tmp,cap[i^1]+=tmp;

    } 

}

int main()

{

    int n=read();

    s1=n+n+1,t1=s1+1,s=0,t=t1+1;

    for(int i=1;i<=n;i++)

        a[i].x=read(),a[i].y=read();

    sort(a+1,a+n+1);

    for(int i=1;i<=n;i++)

        adde(s1,i,1,0),

        adde(i,i+n,1,-1),

        adde(i,i+n,1,0),

        adde(i+n,t1,1,0);

    adde(s,s1,2,0);

    adde(t1,t,2,0);

    for(int i=1;i<=n;i++)

    {

        int tmp=inf;

        for(int j=i+1;j<=n;j++)

        {

            if(a[j].y<tmp&&a[j].y>=a[i].y)

                adde(i+n,j,2,0);

            if(a[j].y>=a[i].y)

                tmp=min(tmp,a[j].y);

        }

    }

    mcf();

    printf("%d\n",-ans);

    return 0;

}

 


评论

热度(6)