4950: [Wf2017]Mission Improbable
Time Limit: 1 Sec Memory Limit: 1024 MBSubmit: 195 Solved: 90
[Submit][Status][Discuss]
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
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
9
样例2
30
HINT
Source
如果当前点的值不是所在行的最大值,不是所在列的最大值。那么就可以把他取到只剩1个
如果一行的最大值和一列的最大值相同,则可以放一个最大值在他的交点处,将这个行与这个列连边(可能存在两行与一列的最大值都相同的情况),所以最后跑二分图匹配
1 #include "bits/stdc++.h" 2 using namespace std; 3 typedef long long LL; 4 const int MAX=105; 5 int n,m,a[MAX][MAX],b[MAX][MAX],fa[MAX],mn[MAX],mm[MAX]; 6 bool vis[MAX]; 7 LL ans; 8 int dfs(int x){ 9 int i,j; 10 for (i=1;i<=m;i++){ 11 if (!vis[i] && b[x][i]){ 12 vis[i]=true; 13 if (fa[i]==-1 || dfs(fa[i])){ 14 fa[i]=x; 15 return 1; 16 } 17 } 18 } 19 return 0; 20 } 21 int main(){ 22 freopen ("mission.in","r",stdin);freopen ("mission.out","w",stdout); 23 int i,j; 24 scanf("%d%d",&n,&m); 25 for (i=1;i<=n;i++) 26 for (j=1;j<=m;j++){ 27 scanf("%d",&a[i][j]); 28 mn[i]=max(mn[i],a[i][j]),mm[j]=max(mm[j],a[i][j]); 29 if (a[i][j]) ans+=a[i][j]-1; 30 } 31 memset(fa,-1,sizeof(fa)); 32 for (i=1;i<=n;i++) if (mn[i]) ans-=mn[i]-1; 33 for (j=1;j<=m;j++) if (mm[j]) ans-=mm[j]-1; 34 for (i=1;i<=n;i++) 35 for (j=1;j<=m;j++) 36 if (a[i][j] && mn[i]==mm[j]) 37 b[i][j]=1; 38 for (i=1;i<=n;i++){ 39 memset(vis,false,sizeof(vis)); 40 if (dfs(i)) ans+=mn[i]-1; 41 } 42 printf("%lld",ans); 43 return 0; 44 }
未来是什么样,未来会发生什么,谁也不知道。
但是我知道,
起码从今天开始努力,
肯定比从明天开始努力,
要快一天实现梦想。
千里之行,始于足下! ——《那年那兔那些事儿》