• BZOJ3140:[HNOI2013]消毒——题解


    http://www.lydsy.com/JudgeOnline/problem.php?id=3140

    https://www.luogu.org/problemnew/show/P3231

    最近在生物实验室工作的小T遇到了大麻烦。 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为a*b*c,a、b、c 均为正整数。为了实验的方便,它被划分为a*b*c个单位立方体区域,每个单位立方体尺寸为1*1*1。用(i,j,k)标识一个单位立方体,1 <=i<=a,1<=j<=b,1<=k<=c。这个实验皿已经很久没有人用了,现在,小T被导师要求将其中一些单位立方体区域进 行消毒操作(每个区域可以被重复消毒)。

    而由于严格的实验要求,他被要求使用一种特定 的F试剂来进行消毒。 这种F试剂特别奇怪,每次对尺寸为x*y*z的长方体区域(它由x*y*z个单位立方体组 成)进行消毒时,只需要使用min{x,y,z}单位的F试剂。F试剂的价格不菲,这可难倒了小 T。

    现在请你告诉他,最少要用多少单位的F试剂。(注:min{x,y,z}表示x、y、z中的最小 者。)

    参考:洛谷两个题解。

    论算法很简单,但是思路真不好想。

    首先对于二维来讲,最优的策略就是每次消毒一行/列。

    那么对于三维同样适用。

    二维的解题思路可以参考:POJ3041:Asteroids

    但是现在是三维的怎么办?拍成二维的即可。

    我们发现一定有min(a,b,c)<=17,于是我们可以令a<=17,这样我们枚举一维a是否被去除,然后将剩下的拍扁成二维做即可。

    (PS:bzoj卡常,这个代码也只是刚好卡过。)

    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=5050;
    struct node{
        int to,nxt;
    }e[N];
    int cnt,t,a,b,c,ans,shu[N],head[N],vis[N];
    int mp[4][N],tot,res;
    bool ok[N];
    inline void add(int u,int v){
        e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
    }
    bool dfs(int u,int id){
        for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(vis[v]!=id){
            vis[v]=id;
                if(!shu[v]||dfs(shu[v],id)){
                    shu[v]=u;
                    return 1;
                }
        }
        }
        return 0;
    }
    void solve(int x){
        for(int i=1;i<=b;i++)head[i]=0;
        for(int i=1;i<=c;i++)vis[i]=shu[i]=0;
        cnt=res=0;
        for(int i=0;i<a;i++){
        if(x&(1<<i)){
            ok[i+1]=0;
            res++;
            if(res>=ans)return;
        }
        else ok[i+1]=1;
        }
        for(int i=1;i<=tot;i++){
        if(ok[mp[1][i]])
            add(mp[2][i],mp[3][i]);
        }
        for(int i=1;i<=b;i++){
        if(dfs(i,i))res++;
        if(res>=ans)return;
        }
        ans=res;
    }
    int main(){
        scanf("%d",&t);
        while(t--){
        tot=0;ans=2147483647;
        scanf("%d%d%d",&a,&b,&c);
        for(int i=1;i<=a;i++){
            for(int j=1;j<=b;j++){
            for(int k=1;k<=c;k++){
                int x;scanf("%d",&x);
                if(x){
                mp[1][++tot]=i;
                mp[2][tot]=j;
                mp[3][tot]=k;
                }
            }
            }
        }
        int minn=min(a,min(b,c));
        if(minn==b)swap(a,b),swap(mp[1],mp[2]);
        else if(minn==c)swap(a,c),swap(mp[1],mp[3]);
        for(int i=0;i<(1<<a);i++)
            solve(i);
        printf("%d
    ",ans);
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    穿越之我是码农 1024 篇
    误删文件机房停电黑客入侵_你最怕什么?
    AI觉醒进行时:程序员你怕了吗?
    未来已来!阿里小蜜AI技术揭秘
    千人千面智能淘宝店铺背后的算法研究登陆人工智能顶级会议AAAI 2017
    CDN缓存不命中排查
    现实需求巨大_技术尚未成熟_学界与业界思维大碰撞
    围观阿里云最会赚钱的人!价值2万元邀请码不限量发送
    今晚19:30直播阿里巴巴大规模持续集成的技术演进之路_欢迎免费观看
    工作压力山大?码农这么减压最有效
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8543713.html
Copyright © 2020-2023  润新知