1930: [Shoi2003]pacman 吃豆豆

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1969  Solved: 461
[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

 

[Submit][Status][Discuss]

题目大意:
  两个 PACMAN 吃豆豆。一开始的时候,PACMAN 都在坐标原点的左下方,豆豆都在右上方。

PACMAN 走到豆豆处就会吃掉它。PACMAN 行走的路线很奇怪,只能向走或者向上走,他们行走的路线不可以相交。

请你帮这两个 PACMAN 计算一下,他们俩加起来最多能吃掉多少豆豆。

解析:
  每个点拆成两个,之间连一条流量为1,费用为1的边;
  如果从一个点出发可以到达另一个点,就将前一个点的出点连向后一个点的入点
  跑费用流。但是这样显然是会TLE的
  如果i能到j,j能到k,那么显然无需连i->k这条边 这是一个剪枝
  加了这个剪枝之后可能会WA 因此还要考虑一个点经过多次的情况
  即每个点从入点向出点再连一条流量为1,费用为0的边
  加了这个之后就能过了 剪枝不强 但是没有什么情况能把这个卡掉
  MS是可以证明复杂度是根号级别的

//204 ms

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
const int inf=0x3f3f3f3f;
struct node{int x,y;}g[N];
struct edge{int v,cap,cost,next;}e[N*];int tot=,head[N];
int n,m,ans,S,T,dis[N],Prev[N],flow[N],q[N*];
bool vis[N];
bool cmp(const node &a,const node &b){
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
void add(int x,int y,int z,int cost){
e[++tot].v=y;e[tot].cap=z;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].cap=;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot;
}
bool spfa(){
for(int i=S;i<=T;i++) vis[i]=,dis[i]=-;
//int h=0,t=1; RE*32!!!
//改:用下面的unsigned short或用循环队列
unsigned short h=,t=;q[t]=S;dis[S]=;flow[S]=inf;
while(h!=t){
int x=q[++h];vis[x]=;
for(int i=head[x];i;i=e[i].next){
if(e[i].cap&&dis[e[i].v]<dis[x]+e[i].cost){
dis[e[i].v]=dis[x]+e[i].cost;
Prev[e[i].v]=i;
flow[e[i].v]=min(flow[x],e[i].cap);
if(!vis[e[i].v]){
vis[e[i].v]=;
if(dis[e[i].v]>dis[x])
q[h--]=e[i].v;
else
q[++t]=e[i].v;
}
}
}
}
return dis[T]!=-;
}
void augment(){
for(int i=T;i!=S;i=e[Prev[i]^].v){
e[Prev[i]].cap-=flow[T];
e[Prev[i]^].cap+=flow[T];
}
ans+=dis[T]*flow[T];
}
int main(){
n=read();
for(int i=;i<=n;i++) g[i].x=read(),g[i].y=read();
sort(g+,g+n+,cmp);
int sink=n<<|,sour=sink+;S=;T=sour+;
for(int i=;i<=n;i++){
add(sink,i,,);
add(i,i+n,,);
add(i,i+n,,);
add(i+n,sour,,);
}
for(int i=;i<=n;i++){
int tmp=-;
for(int j=i-;j;j--){
if(g[j].y<=g[i].y&&g[j].y>tmp){
tmp=g[j].y;
add(j+n,i,,);
}
}
}
add(S,sink,,);
add(sour,T,,);
while(spfa()) augment();
printf("%d",ans);
return ;
}

//=================================================================

dp:

首先建出图,f[i][j]表示a吃到了i点,b吃到了j点的最大值,转移的时候转移拓扑序小的那一维,如果i拓扑序小于j,那么转移到f[k][j],否则转移到f[i][k],建出的图边数也要优化,不然会超时。优化的方法是假如i,j连边,那么如果有一条边(i,k),x[k]>x[j]并且y[k]>y[j]那么(i,k)这条边就没有必要存在了。因为先取(i,j)在去(j,k)会比直接取(i,k)要好。

//612 ms

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=;
const int M=;
struct node{int x,y;}g[N];
struct edge{int v,next;}e[N*];int tot,head[N];
int n,cnt,T,rd[N],id[N],ID[N],q[N*];
int f[M][M];
inline void add(int x,int y){
e[++tot].v=y;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].next=head[y];head[y]=tot;
}
inline bool cmp(const node &a,const node &b){
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
inline void top_sort(){
unsigned short h=,t=;q[t]=;
while(h!=t){
int x=q[++h];
id[x]=++cnt;
ID[cnt]=x;
for(int i=head[x];i;i=e[i].next){
if(--rd[e[i].v]==){
q[++t]=e[i].v;
}
}
}
}
inline void dp(int x,int y){
for(int i=head[x];i;i=e[i].next){
int a=e[i].v,b=y;
if(id[a]>id[b]) swap(a,b);
if(a!=b)
f[a][b]=max(f[a][b],f[x][y]+);
else
f[a][b]=max(f[a][b],f[x][y]);
}
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&g[i].x,&g[i].y);
sort(g+,g+n+,cmp);
for(int i=;i<=n;i++){
int tmp=2e9;
for(int j=i+;j<=n;j++){
if(i!=j&&g[i].x<=g[j].x&&g[i].y<=g[j].y&&g[j].y<tmp){
tmp=g[j].y;
rd[j]++;
add(i,j);
}
}
}
T=n+;
for(int i=;i<=n;i++){
add(,i);rd[i]++;
add(i,T);rd[T]++;
}
top_sort();
for(int i=;i<=cnt;i++){
for(int j=i;j<=cnt;j++){
dp(ID[i],ID[j]);
}
}
printf("%d",f[T][T]-);
return ;
}

1930: [Shoi2003]pacman 吃豆豆的更多相关文章

  1. bzoj 1930: [Shoi2003]pacman 吃豆豆 [费用流]

    1930: [Shoi2003]pacman 吃豆豆 题意:两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的 ...

  2. 【BZOJ1930】[Shoi2003]pacman 吃豆豆 最大费用最大流

    [BZOJ1930][Shoi2003]pacman 吃豆豆 Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会 ...

  3. 【BZOJ 1930】 [Shoi2003]pacman 吃豆豆 最大费用最大流

    如果你知道他是网络流的话你就很快会想到一个最大费用最大流的模型,然后你发现可能T,然而你发现你只用增广两次,然后你就开心的打了出来,然后发现被稠密图里spfa的丧病时间复杂度坑了,还是会T.于是我就开 ...

  4. BZOJ1930 [Shoi2003]pacman 吃豆豆

     dp,首先建出图,f[i][j]表示a吃到了i点,b吃到了j点的最大值,转移的时候转移拓扑序小的那一维,如果i拓扑序小于j,那么转移到f[k][j],否则转移到f[i][k],建出的图边数也要优化, ...

  5. [bzoj]1930 pacman吃豆豆

    Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他 ...

  6. 【BZOJ1930】【SHOI2003】吃豆豆

    初见杀…… 原题: 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行 ...

  7. 洛谷 P4066 [SHOI2003]吃豆豆 解题报告

    P4066 [SHOI2003]吃豆豆 题目描述 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪 ...

  8. HTML5吃豆豆游戏开发实战(一)使用Canvas绘制游戏主角

    近期在学习HTML5.爱因斯坦曾说过,"最好的学习就是自己去经历". 于是.我想在学习HTML5的同一时候.做一款简单的小游戏,这样学习起来也会非常有趣的.我想做的是曾经小时候玩儿 ...

  9. css动画实现吃豆豆

    话不多说,直接上代码:(作为一个初学者写的代码,多么0基础都能看的懂吧.) HTML部分 <!DOCTYPE html> <html lang=en> <head> ...

随机推荐

  1. Codeforces 707C. Pythagorean Triples-推公式的数学题

    两道C题题解,能推出来公式简直是无敌. http://codeforces.com/problemset/problem/707/C codeforces707C. Pythagorean Tripl ...

  2. Codeforces 777E Hanoi Factory(线段树维护DP)

    题目链接 Hanoi Factory 很容易想到这是一个DAG模型,那么状态转移方程就出来了. 但是排序的时候有个小细节:b相同时看a的值. 因为按照惯例,堆塔的时候肯定是内半径大的在下面. 因为N有 ...

  3. 10.1综合强化刷题 Day2 afternoon

    最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度为n的 ...

  4. [TJOI2016][HEOI2016]排序

    题目大意: 给定一个$1\sim n(n\leq10^5)$的全排列,有$m(m\leq10^5)$次操作,每次把区间$[l,r]$按照升序或降序排序.最后询问所有操作完成后,位置为$q$的数是多少. ...

  5. mysql二进制安装,升级,多实例部署

    目标 理解线上部署考虑的因素 学会编译安装以及二进制安装mysql 学会升级mysql 学会多实例部署mysql数据库 学会合理部署mysql线上库   考虑因素: 版本选择,5.1,5.5还是5.6 ...

  6. 深入浅出 Cocoa 之 Core Data(2)- 手动编写代码

    深入浅出 Cocoa 之 Core Data(2)- 代码示例 罗朝辉(http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 前面详细讲解了 Core Data 的框 ...

  7. opencv-2.4.11编译备忘

    编译完成后,想测试example中例子,但是由于没有sudo权限,不能运行pkg-config查看opencv的--cflags和--libs. 记录一下,备忘: pkg-config --libs ...

  8. 从有序数组中查找某个值 low_bound

    二分搜索 题意: 给定长度为n的单调不下降数列a0, ...an-1和一个数k,求满足ai>=k条件的最小的i. 不存在的情况下输出n. 输入: 5        3 2 3 3 5 6 输出: ...

  9. 数据结构基础-Hash Table详解(转)

    理解Hash 哈希表(hash table)是从一个集合A到另一个集合B的映射(mapping). 映射是一种对应关系,而且集合A的某个元素只能对应集合B中的一个元素.但反过来,集合B中的一个元素可能 ...

  10. 翻翻git之---一个丰富的通知工具类 NotifyUtil

    转载请注明出处王亟亟的大牛之路 P1(废话板块.今天还加了个小广告) 昨天出去浪,到家把麦麦当当放出来玩一会就整到了12点多..早上睡过头了. .简直心酸. ... 近期手头上有一些职位能够操作,然后 ...