zoukankan      html  css  js  c++  java
  • [HNOI2013]消毒

    题目描述

    最近在生物实验室工作的小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中的最小 者。)

    输入输出格式

    输入格式:

    第一行是一个正整数D,表示数据组数。接下来是D组数据,每组数据开头是三个数a,b,c表示实验皿的尺寸。接下来会出现a个b 行c列的用空格隔开的01矩阵,0表示对应的单位立方体不要求消毒,1表示对应的单位立方体需要消毒;例如,如果第1个01矩阵的第2行第3列为1,则表示单位立方体(1,2,3)需要被消毒。输入保证满足a*b*c<=5000,T<=3。

    输出格式:

    仅包含D行,每行一个整数,表示对应实验皿最少要用多少单位 的F试剂。

    输入输出样例

    输入样例#1: 
    1
    4  4 4
    1  0 1 1
    0  0 1 1
    0  0 0 0
    0  0 0 0
    0  0 1 1
    1  0 1 1
    0  0 0 0
    0  0 0 0
    0  0 0 0
    0  0 0 0
    1  0 0 0
    0  0 0 0
    0  0 0 0
    0  0 0 0
    0  0 0 0
    1  0 0 0
    输出样例#1: 
    3

    说明

    对于区域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。

    题解:

    个人认为这道题很强。。。

    题目要求的是三维,那么我们先考虑一个简化版的问题,如果是二维的,我们应该怎么做?

    不难发现这个简化版的问题是二分图的裸题:

      1.将行和列分别虚拟成两列点。

      2.将每一个格子虚拟成边连在相对应的行和列上。

      3.然后跑一下二分图就好。

    但是如果上升成了三维,我们该怎么办?貌似是不存在三分图的。

    观察一下数据范围,我们可以发现a*b*c<=5000,这说明a,b,c中至少有一个小于等于17。

    于是我们对这最小的一维的状态进行枚举,即当前层是否被全部消毒。这个过程可以用dfs,我用的是循环枚举。

     1 //Never forget why you start
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<algorithm>
     8 #define inf (2000000000)
     9 using namespace std;
    10 const int N=5005;
    11 int t,cnt,x,y,z;
    12 int gi(){
    13   int ans=0,f=1;char i=getchar();
    14   while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
    15   while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
    16   return ans*f;
    17 }
    18 struct point{
    19   int x,y,z;
    20 }p[N];
    21 struct node{
    22   int next,to;
    23 }edge[N];
    24 int head[N],size=0,vis[N],dfscnt,match[N];
    25 void putin(int from,int to){
    26   size++;
    27   edge[size].next=head[from];
    28   edge[size].to=to;
    29   head[from]=size;
    30 }
    31 bool dfs(int r){
    32   int i;
    33   for(i=head[r];i!=-1;i=edge[i].next){
    34     int to=edge[i].to;
    35     if(vis[to]!=dfscnt){
    36       vis[to]=dfscnt;
    37       if(!match[to]||dfs(match[to])){
    38     match[to]=r;
    39     return true;
    40       }
    41     }
    42   }
    43   return false;
    44 }
    45 int solve(int s){
    46   int i,ans=0;
    47   memset(head,-1,sizeof(head));size=0;
    48   memset(match,0,sizeof(match));
    49   for(i=1;i<=cnt;i++)if(!((1<<(p[i].x-1))&s))putin(p[i].y,p[i].z);
    50   for(i=1;i<=s;i<<=1)if(i&s)ans++;
    51   for(i=1;i<=y;i++){
    52     ++dfscnt;
    53     if(dfs(i))ans++;
    54   }
    55   return ans;
    56 }
    57 int main(){
    58   int i,j,k,l;
    59   t=gi();
    60   while(t--){
    61     x=gi();y=gi();z=gi();cnt=0;
    62     for(i=1;i<=x;i++)
    63       for(j=1;j<=y;j++)
    64     for(k=1;k<=z;k++){
    65       l=gi();
    66       if(l){
    67         p[++cnt].x=i;
    68         p[cnt].y=j;
    69         p[cnt].z=k;
    70       }
    71     }
    72     if(z<y&&x>z){
    73       swap(x,z);
    74       for(i=1;i<=cnt;i++)swap(p[i].x,p[i].z);
    75     }
    76     if(y<x&&y<z){
    77       swap(x,y);
    78       for(i=1;i<=cnt;i++)swap(p[i].x,p[i].y);
    79     }
    80     int tot=(1<<x)-1,ans=inf;
    81     for(i=0;i<=tot;i++)ans=min(ans,solve(i));
    82     printf("%d
    ",ans);
    83   }
    84   return 0;
    85 }
  • 相关阅读:
    LeetCode 242. Valid Anagram (验证变位词)
    LeetCode 205. Isomorphic Strings (同构字符串)
    LeetCode 204. Count Primes (质数的个数)
    LeetCode 202. Happy Number (快乐数字)
    LeetCode 170. Two Sum III
    LeetCode 136. Single Number (落单的数)
    LeetCode 697. Degree of an Array (数组的度)
    LeetCode 695. Max Area of Island (岛的最大区域)
    Spark中的键值对操作
    各种排序算法总结
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8260886.html
Copyright © 2011-2022 走看看