首页 > 其他 > 详细

bzoj4950

时间:2017-08-30 23:09:33      阅读:338      评论:0      收藏:0      [点我收藏+]

[Wf2017]Mission Improbable

Time Limit: 1 Sec  Memory Limit: 1024 MB
Submit: 105  Solved: 49
[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

Sample Output

样例1
9
样例2
30

HINT

这道题上午的时候司机和我说了一下,想的和正解差不多,最后没想到二分图匹配。。。但是感觉暴力也可以啊。
就是能拿的都拿成1,然后每行每列上都放上当前这行这列的最大数,如果某一行最大值和某一列最大值相同,则在交点处放1个,如果原来是0就不行,这时候用二分图搞一下就可以了。
写完的时候bzoj刚好炸了/(ㄒoㄒ)/~~
先放着
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int level[105][105],num,to[40005],next[40005],head[205],match[205],mr[105],mc[105],used[205],r,c,u,v;
long long sum;
void make_way(int u,int v)
{
    to[++num]=v;
    next[num]=head[u];
    head[u]=num;
}
bool dfs(int u)
{
    int t;
    for(int edge=head[u];edge;edge=next[edge])
    if(!used[to[edge]])
    {
        int v=to[edge];
        t=match[v];
        used[v]=1;
        match[v]=u;
        if(!t||dfs(t)) return 1;
        match[v]=t;
    }
    return 0;
}
int main()
{
    scanf("%d %d",&r,&c);
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        {
            scanf("%d",&level[i][j]);
            mr[i]=max(mr[i],level[i][j]);
            mc[j]=max(mc[j],level[i][j]);
            if(level[i][j]) sum+=level[i][j]-1;
        }
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        if(mr[i]==mc[j]&&level[i][j])
        {
            make_way(i,r+j);
        }
    for(int i=1;i<=r;i++)
    if(mr[i]) sum-=mr[i]-1;    
    for(int j=1;j<=c;j++)
    if(mc[j]) sum-=mc[j]-1;
    
    for(int i=1;i<=r;i++)
    {
        memset(used,0,sizeof(used));
        if(dfs(i)) sum+=mr[i]-1;
    }
    cout<<sum<<endl;
                
}

 

 

bzoj4950

原文:http://www.cnblogs.com/dancer16/p/7455726.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!