【bzoj4950】【 [Wf2017]Mission Improbable】贪心+二分图匹配
(上不了p站我要死了,侵权度娘背锅)
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
从题目中我们可以获得思路:先全部拿走,再放回去,要求放回去的值最小。(这是贪心)
那么拿走了怎么放回去呢?首先,要保证每行每列的最大高度不变,所以在拿走了之后要还回去。其次,如果把每行每列的最大值都还回去,肯定不优,因为可能某一行某一列的最大值相等,只用将这个最大值摆在交点位置就可以了。那么就将多放回去的再拿走。
但是有一个问题,如果多列的最大值和多行的最大值相等,我们难以确定让哪一个交点作为该行和该列的最大值。每一行最多有一列让我们重新拿回去,其他的最值要作为其他列的最值。
现在问题就转为了如何取走最多的物品,使得这些物品的行列不同。就是一个二分图的最大匹配了。
在“还”的时候忘记了如果这一行(列)的最高高度为0,就不用还回去。wa了我好久。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
template <typename T>inline void read(T &res){
T k=1,x=0;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-')k=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
res=x*k;
}
const int N=100+5;
int n,m;
ll h[N][N],rr[N],cc[N];
int bl[N];
bool vis[N];
int head[N],end[N*N],nxt[N*N],hh=0;
ll ans=0;
void adde(int a,int b){
hh++;
end[hh]=b;
nxt[hh]=head[a];
head[a]=hh;
}
bool find(int u){
for(int i=head[u];i;i=nxt[i]){
int v=end[i];
if(vis[v]) continue;
vis[v]=1;
if(bl[v]==0||find(bl[v])){
bl[v]=u;
return true;
}
}
return false;
}
int main(){
read(n),read(m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
read(h[i][j]);
rr[i]=max(rr[i],h[i][j]);
cc[j]=max(cc[j],h[i][j]);
if(h[i][j]) ans+=h[i][j]-1;
}
}
for(int i=1;i<=n;i++) if(rr[i]) ans-=rr[i]-1;
for(int j=1;j<=m;j++) if(cc[j]) ans-=cc[j]-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(rr[i]==cc[j]&&h[i][j]) adde(i,j);
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(find(i)) ans+=rr[i]-1;
}
cout<<ans<<endl;
return 0;
}
【bzoj4950】【 [Wf2017]Mission Improbable】贪心+二分图匹配的更多相关文章
- bzoj4950: [Wf2017]Mission Improbable
跟着靖靖做题%%%%% 这题一看就觉得和之前的某场模拟赛的一道题很像,找假如某行某列的最大值一样的就可以只堆一个,跑匈牙利就行 一开始以为箱子不能移动-_-! 然后有个坑,大家都知道当这个位置有箱子就 ...
- 4950: [Wf2017]Mission Improbable
4950: [Wf2017]Mission Improbable Time Limit: 1 Sec Memory Limit: 512 MBSubmit: 608 Solved: 222[Sub ...
- 洛谷$P1155$ 双栈排序 贪心+二分图匹配
正解:贪心+二分图匹配 解题报告: 传送门$QwQ$ 跪了,,,我本来以为我$NOIp$做得差不多了,,,然后康了一眼发现没做多少啊其实$QAQ$ 然后来康题趴$QwQ$ 首先考虑如果只有一个栈的情况 ...
- BZOJ4950 Wf2017Mission Improbable(二分图匹配)
先给每个非零格子-1以满足俯视图不变.于是就相当于要求每行每列最大值不变.能减少剩余箱子的唯一方法是在要求相同的行列的交叉处放箱子以同时满足两个需求.给这些行列连边跑二分图匹配即可.注意必须格子初始时 ...
- 【刷题】BZOJ 4950 [Wf2017]Mission Improbable
Description 那是春日里一个天气晴朗的好日子,你准备去见见你的老朋友Patrick,也是你之前的犯罪同伙.Patrick在编程竞赛上豪赌输掉了一大笔钱,所以他需要再干一票.为此他需要你的帮助 ...
- HDU 4619 Warm up 2 贪心或者二分图匹配
给同一张横着的牌的所在的格子编同一样的号,这些格子对应x集合,给同一张竖着的牌所在的格子编同一样的号,对应y集合,同一个格子上既有横着的牌又有竖着的牌,那么就建一条边,有冲突就要拿走一张,结果是总的牌 ...
- HDU5090--Game with Pearls 二分图匹配 (匈牙利算法)
题意:给N个容器,每个容器里有一定数目的珍珠,现在Jerry开始在管子上面再放一些珍珠,放上的珍珠数必须是K的倍数,可以不放.最后将容器排序,如果可以做到第i个容器上面有i个珍珠,则Jerry胜出,反 ...
- HDOJ 5093 Battle ships 二分图匹配
二分图匹配: 分别按行和列把图展开.hungary二分图匹配. ... 例子: 4 4 *ooo o### **#* ooo* 按行展开. .. . *ooo o#oo oo#o ooo# **#o ...
- 二分图匹配之最佳匹配——KM算法
今天也大致学了下KM算法,用于求二分图匹配的最佳匹配. 何为最佳?我们能用匈牙利算法对二分图进行最大匹配,但匹配的方式不唯一,如果我们假设每条边有权值,那么一定会存在一个最大权值的匹配情况,但对于KM ...
随机推荐
- Java基本-2对象与包
1.对象:通俗的来讲,就是一个东西,比如汽车是一个对象,人是一个对象,狗是一个对象. 2.类:她描述的是对象的行为或者状态,比如对象是汽车,那么嘞可以分为小汽车类,大货车类,客车类等. 在类中可以包含 ...
- springboot配多数据源
多数据源配置 https://blog.csdn.net/neosmith/article/details/61202084 https://www.cnblogs.com/zhangboyu/p/7 ...
- Python基础简介与简单使用
Python介绍 Python发展史 1989年,为了打发圣诞节假期,Guido开始写Python语言的编译器.Python这个名字,来自Guido所挚爱的电视剧Monty Python’s Flyi ...
- Linux(Ubuntu 命令大全)
Ubuntu 一. Ubuntu简介 Ubuntu(乌班图)是一个基于Debian的以桌面应用为主的Linux操作系统,据说其名称来自非洲南部祖鲁语或科萨语的“ubuntu”一词,意思是“人性”.“我 ...
- 【Python】重定向 Stream 到文件
Python 系统模块 sys 中有三个变量 stdin . stdout 与 stderr ,分别对应标准输入流.输出流与错误流.stdin 默认指向键盘, stdout 与 stderr 默认指向 ...
- shell之小知识点
last:显示/var/log/wtmp文件,显示用户登录历史及重启历史 -n #:仅显示最近几次的相关信息 lastb:/var/log/btmp文件,显示用户错误的登录尝试 -n ...
- TOJ 3046: 招商银行网络系统
3046: 招商银行网络系统 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 12 ...
- HDU 4107 Gangster(线段树 特殊懒惰标记)
两种做法. 第一种:标记区间最大值和最小值,若区间最小值>=P,则本区间+2c,若区间最大值<P,则本区间+c.非常简单的区间更新. 最后发一点牢骚:最后query查一遍就行,我这个2B竟 ...
- [译]在python中如何有效的比较两个无序的列表是否包含完全同样的元素(不是set)?
原文来源: https://stackoverflow.com/questions/7828867/how-to-efficiently-compare-two-unordered-lists-not ...
- SQL Server 重新编译存储过程的方式有三种
SQL Server 中,强制重新编译存储过程的方式有三种: sp_recompile 系统存储过程强制在下次执行存储过程时对其重新编译.具体方法是:从过程缓存中删除现有计划,强制在下次运行该过程时创 ...