BZOJ1930 [Shoi2003]pacman 吃豆豆

SHOI出过这么鬼的题?、、跪

首先我们可以想到费用网络流,找一个流量为2的最大费用流即可,问题是怎么建图

因为针对点才有收益,而且收益只有一次,所以考虑拆点,不妨设一个点p拆成入点p1和出点p2

则p1 -> p2连边流量为1,费用为1;再连边流量为1,费用为0;S向p1连边流量为1,费用为0;p2向T连边,流量为1,费用为0

若p能到达q,则p2 -> q1连边,流量为2,费用为0

然后会发现边太多。。。优化?

如果i能到达j,j能到达k,则i不要向k连边,于是就是一个单调性的问题,对点按x轴排序,然后按照y轴单调增加的方式连边。

  1 /**************************************************************
  2     Problem: 1930
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:192 ms
  7     Memory:63416 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <algorithm>
 12
 13 using namespace std;
 14 const int N = 2015;
 15 const int M = 4e6 + 5;
 16 const int inf = 1e9;
 17
 18 inline int read() {
 19     int x = 0;
 20     char ch = getchar();
 21     while (ch < ‘0‘ || ‘9‘ < ch)
 22         ch = getchar();
 23     while (‘0‘ <= ch && ch <= ‘9‘) {
 24         x = x * 10 + ch - ‘0‘;
 25         ch = getchar();
 26     }
 27     return x;
 28 }
 29
 30 struct point {
 31     int x, y;
 32
 33     inline void read_in() {
 34         x = read(), y = read();
 35     }
 36     inline bool operator < (const point &p) const {
 37         return x == p.x ? y < p.y : x < p.x;
 38     }
 39 } p[N];
 40
 41 struct edges {
 42     int next, to, f, cost;
 43     edges() {}
 44     edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
 45 } e[M];
 46
 47 int n, S, S1, T;
 48 int first[N << 1], tot = 1;
 49 int a[N];
 50 int d[N << 1], g[N << 1], q[N << 1], vis[N << 1];
 51 bool v[N << 1];
 52
 53 inline void Add_Edges(int x, int y, int f, int c) {
 54     e[++tot] = edges(first[x], y, f, c), first[x] = tot;
 55     e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
 56 }
 57
 58 inline int calc() {
 59     int flow = inf, x;
 60     for (x = g[T]; x; x = g[e[x ^ 1].to])
 61         flow = min(flow, e[x].f);
 62     for (x = g[T]; x; x = g[e[x ^ 1].to])
 63         e[x].f -= flow, e[x ^ 1].f += flow;
 64     return flow;
 65 }
 66
 67 #define y e[x].to
 68 bool spfa() {
 69     int x, now, l, r;
 70     for (x = 1; x <= S1; ++x)
 71         d[x] = inf;
 72     d[S] = 0, v[S] = 1, q[0] = S;
 73     for(l = r = 0; l != (r + 1) % N; ) {
 74         now = q[l], ++l %= N;
 75         for (x = first[now]; x; x = e[x].next) {
 76             if (d[now] + e[x].cost < d[y] && e[x].f) {
 77                 d[y] = d[now] + e[x].cost, g[y] = x;
 78                 if (!v[y]) {
 79                     v[y] = 1;
 80                     if (d[y] < d[q[l]])
 81                         q[(l += N - 1) %= N] = y;
 82                     else q[++r %= N] = y;
 83                 }
 84             }
 85         }
 86         v[now] = 0;
 87     }
 88     return d[T] != inf;
 89 }
 90 #undef y
 91
 92 inline int work() {
 93     int res = 0;
 94     while (spfa())
 95         res += calc() * d[T];
 96     return res;
 97 }
 98
 99 #define p1(i) (i << 1) - 1
100 #define p2(i) (i << 1)
101 int main() {
102     int i, j, tmp;
103     n = read(), S = n * 2 + 1, T = S + 1, S1 = T + 1;
104     for (i = 1; i <= n; ++i)
105         p[i].read_in();
106     sort(p + 1, p + n + 1);
107     for (i = 1; i <= n; ++i) {
108         a[i] = p[i].y, tmp = -1;
109         Add_Edges(S1, p1(i), 1, 0), Add_Edges(p2(i), T, 1, 0);
110         Add_Edges(p1(i), p2(i), 1, -1), Add_Edges(p1(i), p2(i), 1, 0);
111         for (j = i - 1; j; --j)
112             if (a[j] <= a[i] && a[j] > tmp)
113                 tmp = a[j], Add_Edges(p2(j), p1(i), 2, 0);
114     }
115     Add_Edges(S, S1, 2, 0);
116     printf("%d\n", -work());
117     return 0;
118 }

时间: 2024-10-21 13:49:57

BZOJ1930 [Shoi2003]pacman 吃豆豆的相关文章

BZOJ1930 [Shoi2003]pacman 吃豆豆 费用流

题目大意:在二维平面上有若干个点,求出两条不相交的二维LIS,使得上面包含的点的数目最多. 思路1:暴力建图 注意到不相交这个条件根本没用,画图可以发现如果相交的话,我们总可以通过交换一些点使得两个序列不相交. 那么问题转化为求出两个没有公共点的上升子序列,使得长度之和最大. 对于这种情况我们利用最大费用流求解. 设(a,b)分别表示一条有向边的流量和费用. S->S' (2,0) S'->x(1,0),x'->T(1,0)(1<=x<=n) x->x' (1,1) 表

BZOJ 1930 Shoi2003 pacman 吃豆豆 费用流

题目大意:给定一个平面上的一些点,吃豆先生从原点出发,只能向右或向上走,求两个吃豆先生最多吃到多少豆 每个点拆成两个,之间连一条流量为1,费用为1的边: 如果从一个点出发可以到达另一个点,就将前一个点的出点连向后一个点的入点 跑费用流.但是这样显然是会TLE的 如果i能到j,j能到k,那么显然无需连i->k这条边 这是一个剪枝 加了这个剪枝之后可能会WA 因此还要考虑一个点经过多次的情况 即每个点从入点向出点再连一条流量为1,费用为0的边 加了这个之后就能过了 剪枝不强 但是没有什么情况能把这个

【BZOJ1930】【SHOI2003】吃豆豆

初见杀-- 原题: 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行走的路线不可以相交. 请你帮这两个PACMAN计算一下,他们俩加起来最多能吃掉多少豆豆. N < = 2000 一眼秒掉,拆点费用流 然后发现内存64M???减少边的数组,提交,RE-- 看chty的题解,更换建图方式,减少边数,提交,WA-- 然后我的上午没了 解题思路很简单,拆点费用流即可,关键

BZOJ 1930 SHOI 2003 pacman 吃豆豆 费用流

题目大意:给出一些平面上的点,你有两个吃豆人,从一个点出发,这个吃豆人可以吃到当前点右上方的点.问这两个吃豆人最多可以吃到多少豆子. 思路:我已經吧不相交的条件去掉了.. 不加优化的费用流模型很明显 超级源->源 flow2 cost0 汇->超级汇 flow2 cost0 下面是拆点 i << 1 -> i << 1|1 flow1 cost1 对于从点i能够到达点j的情况 i << 1|1 - > j << 1 flow1 cos

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

最近在学习HTML5,爱因斯坦曾说过,"最好的学习就是自己去经历".于是,我想在学习HTML5的同时,做一款简单的小游戏,这样学习起来也会很有趣的,我想做的是以前小时候玩儿的小霸王上面的很经典的一款游戏,叫"吃豆豆",后面有怪物跟着跑,蛮好玩的,还很虐心,相信大家都玩儿过. 吃豆豆就是这款啦: 我就用前面学的一些HTML5的简单的一些知识来简单模拟这款游戏吧.我做这款游戏不打算用图片,全部用canvas来画,这样才有意思,嘿嘿. 正如大家所看到的,我们游戏的主角就是

P4066 [SHOI2003]吃豆豆

我和这道题的邂逅,是在那个曼妙的周五的夜晚. 作为一道模拟题,她很好地履行了她的职责,不让我会…… 言归正传… 其实在离模拟结束还有14分钟的时候我想出来了费用流的写法……(70分),但是显然我有一段时间没有写网络流了,再加上时间太短,就没有去写. 这道题和传纸条好像啊……我一开始考虑dp,但是范围太大了,没法下手……再转念一想——不就是这两条路径上的点最多嘛?而对于不能交叉,我们还能联想到网络流的流量限制. 于是——最大费用最大流. 对于一个点只能选一次的限制,都是网络流的常规套路了——拆点建

2014061404吃豆豆(C++)

#include<cstdio> #include<algorithm> #define N 10010 using namespace std; int n,i,j,rd[N],t,w,tot,id[N]; int dp,pre[3000000],p[N],tt[3000000],z[N],ID[N],tmp; int f[2500][2500]; struct g{ int x,y; }a[N]; bool cmp(g a,g b) { if (a.x==b.x) return

HTML5吃豆豆游戏开发实战(四)2d碰撞检测、重构-第二篇

今天下午在家没事,写代码.先总结一下学习HTML5和JS的一些经验,再来说游戏的事吧! 这完全是一个HTML5和JS的入门新手的见解,如果您和我一样是新手的话,欢迎交流,当然,高手如果不介意的话,帮小弟指点一二那就更好啦,谢谢,嘿嘿!入正题吧! 1.语法方面 1.1  JS关于数组的定义方法要注意: 比如:var walls = [new Wall(262,200,100,30),new Wall(662,60,30,400),new Wall(762,300,200,30)]; 这是定义一个墙

HTML5吃豆豆游戏开发实战(二)主角移动和动画循环设置

接着上一篇讲,在上一篇中呢,我已经使用Canvas绘制出了我们游戏的主角,姑且叫它"小嘴"吧,因为只有嘴巴,嘿嘿,我还添了眼睛. 在这一篇中呢,就实现物体的移动和动画播放(一直张开嘴吧关闭嘴巴的动画,很饥渴的样子). 1. 要做玩家和游戏的交互,当然要考虑--如何设置按键响应这个问题. 那么如何设置呢? 我们可以通过在body标签里面添加事件来响应用户的操作: 由于我们要用W,A,S,D来控制物体的上下移动,这是按键响应,于是我们选择用onkeydown事件. onkeydown 事件