BZOJ 4950 Mission Improbable (二分图最大匹配)
来源:互联网 发布:java 邮箱匹配 编辑:程序博客网 时间:2024/04/26 05:02
4950: [Wf2017]Mission Improbable
Time Limit: 1 Sec Memory Limit: 1024 MB
Description
那是春日里一个天气晴朗的好日子,你准备去见见你的老朋友Patrick,也是你之前的犯罪同伙。Patrick在编程竞赛
上豪赌输掉了一大笔钱,所以他需要再干一票。为此他需要你的帮助,虽然你已经金盆洗手了。你刚开始很不情愿,
因为你一点也不想再回到那条老路上了,但是你觉得听一下他的计划也无伤大雅。在附近的一个仓库里有一批货物,
包含一些贵重的消费性部件,Patrick企图从中尽可能多地偷些东西出来。这意味着要找一条进去的路,弄晕安保人
员,穿过各种各样的激光射线,你懂的,都是常见的抢劫技术。然而,仓库的核心装备了一套Patrick搞不定的安保系
统。这也是他需要你帮助他的地方。这批货物被放置在一些巨大的立方体箱里,每个箱子的尺寸都是相同的。这些
箱子堆放成许多整齐的堆,每个箱子可以表示成一个三维的网格。安保系统每个小时会用三台相机对这堆货物进行
一次拍照,相机分别为:前置相机(front camera),侧置相机(side camera)和顶置相机(top camera)。前置相机的照
片显示了每一行最高的那堆箱子的高度,侧置相机显示了每一列最高的那堆箱子的高度,顶置相机显示了每个位置是
否存在一堆箱子。如果安保系统发现任何一张照片出现了变化,它会立即拉响警报。一旦 Patrick 进去了,他会确
定每堆箱子的高度并且发给你。图1显示了一种网格可能的放置,以及每台相机会得到的视图。
图 1. 网格的高度值与对应的相机视图。
图 2. 洗劫后网格可能的高度值。
Patrick想尽可能多偷走一些箱子。由于他不能弄坏安保系统,他准备重新安排剩余每堆箱子的放置,使得下一次相
机取像时会得到相同的照片,从而骗过安保系统。在上面的例子中,他可以偷走九个箱子。图2显示了一种可能的剩
余箱子的安置方案能使得安保系统认为与原安置情况相同。Patrick想请你帮他确定在保证能骗过安保系统的情况
下他最多能偷走多少个箱子。你会帮他干完这最后一票么?
Input
第一行包含两个整数r(1≤r≤100)和c(1≤n≤100),分别表示网格的行数与列数。
接下来r行,每行包含c个整数,表示对应行上每堆立方体箱的高度(箱子的数量)。
所有的高度在0到10^9之间 (含边界) 。
Output
输出在不被发现的情况下最多能偷走多少箱子。
Sample Input
样例1
5 5
1 4 0 5 2
2 1 2 0 1
0 2 3 4 4
0 3 0 3 1
1 2 2 1 1
样例2
2 3
50 20 3
20 10 3
Sample Output
样例1
9
样例2
30
思路:
对于俯视图,我们使有箱子的格子不被拿完即可。对于侧视图和正视图,使行和列的最大值保持不变即可。
注意到某一行和某一列的最大值可能相同,对此,我们将尽量保留这样的最大值。
但是如果有一个位置既是行的最大值也是列的最大值,那么我们就把它留下了两次,要尽可能的去重,将这种pos的行和列连边,跑一遍二分图最大匹配即可。
#include <cstdio>#include <cstring>#include <iostream>#define LL long long#define N 110#define M 10010 using namespace std;int n, m, idc, now;LL ans;LL map[N][N], s1[N], s2[N];int head[N], vis[N], lnk[N];struct Edge{ int to, nxt;}ed[M];void adde(int u, int v){ ed[++idc].to = v; ed[idc].nxt = head[u]; head[u] = idc;}int find(int u){ for(int i=head[u]; i; i=ed[i].nxt){ int v = ed[i].to; if( vis[v] ) continue; vis[v] = 1; if(!lnk[v] || find(lnk[v])){ lnk[v] = u; /*lnk[u] = v;*/ return 1; } } return 0;}//是否在最大匹配上(是否是我们选择的行列都是最大值的pos) int main(){ scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++){ scanf("%lld", &map[i][j]); s1[i] = max(s1[i], map[i][j]); s2[j] = max(s2[j], map[i][j]); ans += map[i][j];//全部移走 } for(int i=1; i<=n; i++) for(int j=1; j<=m; j++){ if( map[i][j] ){ ans--;//通过俯视图是否留下一块 if(s1[i]>1 && s1[i]==s2[j]) adde(i, j)/*, adde(j, i)*/;//这个格子既是行的最大值又是列的最大值 } } for(int i=1; i<=n; i++) if( s1[i] ) ans -= s1[i] - 1;//行列最大值不能移走 for(int i=1; i<=m; i++) if( s2[i] ) ans -= s2[i] - 1; for(int i=1; i<=n; i++) if( s1[i] ) memset(vis, 0, sizeof(vis)), ans += find( i ) * (s1[i] - 1); //行列都是最大值的pos我们减了两次,所以要加回来(要加的最多就跑最大匹配) printf("%lld", ans); return 0;}
- BZOJ 4950 Mission Improbable (二分图最大匹配)
- bzoj 4950: [Wf2017]Mission Improbable(二分匹配)
- bzoj4950 [Wf2017]Mission Improbable(二分图最大匹配)
- BZOJ4950 [Wf2017][Mission Improbable] 二分图匹配
- bzoj4950: [Wf2017]Mission Improbable 二分图匹配
- 【bzoj4950】【 [Wf2017]Mission Improbable】贪心+二分图匹配
- bzoj 4950(二分图最大匹配)
- [BZOJ]4950 二分图 + 最大匹配
- BZOJ 1191(二分图最大匹配)
- bzoj 4443(二分+二分图最大匹配)
- BZOJ 4950 [Wf 2017] 二分图最大匹配 解题报告
- BZOJ 1059 矩阵游戏 (二分图最大匹配)
- BZOJ 1059-矩阵游戏(二分图最大匹配)
- 【bzoj 1059】矩阵游戏(二分图最大匹配)
- [BZOJ]3140 二分图最大匹配
- 二分图(最大匹配)
- 【二分图最大匹配】[SCOI2010] 游戏 BZOJ 1854
- [二分图匹配][各种优化][BZOJ 2034]最大收益
- MySQL下删除重复记录只保留一条数据
- 10.2ZWJ
- 计算 -2
- Gym101194A-Number Theory Problem
- navicate连接oracle
- BZOJ 4950 Mission Improbable (二分图最大匹配)
- ida算法解析
- IO基础(2)-IO缓冲流及其他流用法
- 面试题(一)- 谈谈你对数据库中索引的理解
- mini版镜像Centos(无图形化界面)搭建集群环境(MAC地址冲突或者无效的解决方法)
- 机器学习 第六周 总结 知识点
- python matplotlib 入门系列三:坐标轴
- 【c基础知识】内存分区
- Mysql-mytop安装与使用