bzoj3140 [Hnoi2013]消毒
Description
最近在生物实验室工作的小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中的最小 者。)
Input
Output
仅包含D行,每行一个整数,表示对应实验皿最少要用多少单位 的F试剂。
Sample Input
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
Sample Output
HINT
对于区域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。2017.5.26新加两组数据By Leoly,未重测.
正解:搜索+二分图匹配。
我们考虑弱化一下条件,假设只有两维,这道题应该怎么做呢?
很显然,我们每次都会选择$[a,m]$或$[n,b]$的矩形进行覆盖,换句话说,我们每次就是覆盖一行或者一列。
那么二维的情况就是二分图最小点覆盖,那么就等于最大匹配,于是我们直接把行向列连边,跑匈牙利就行了。
三维的情况似乎不那么好做了,但是我们注意到$a*b*c\leq 5000$,也就是说,最小的那个数$\leq 17$。
我们可以直接把$c$变成最小值,然后爆搜每一层是否直接消毒,直接消毒代价为$1$。
我们把剩下还没有消毒的层拼在一起,那么它们消毒的代价肯定是行或列。那么我们跑一遍匈牙利就行了。
复杂度$O(2^{c}*a*b)$。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define pos(i,j,k) ((i-1)*b*c+(j-1)*c+k) 6 7 using namespace std; 8 9 int e[5005][5005],vis[5005],lk[5005],sz[5005],d[5005],a,b,c,cnt,ans; 10 11 il int gi(){ 12 RG int x=0,q=1; RG char ch=getchar(); 13 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 14 if (ch=='-') q=-1,ch=getchar(); 15 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 16 return q*x; 17 } 18 19 il int dfs(RG int x){ 20 for (RG int i=1;i<=c;++i){ 21 if (!e[x][i] || vis[i]==cnt) continue; vis[i]=cnt; 22 if (!lk[i] || dfs(lk[i])) return lk[i]=x,1; 23 } 24 return 0; 25 } 26 27 il void dfs(RG int x,RG int tot){ 28 if (x>a){ 29 for (RG int i=1;i<=c;++i) vis[i]=lk[i]=0; cnt=0; 30 for (RG int i=1;i<=b;++i) ++cnt,tot+=dfs(i); 31 ans=min(ans,tot); return; 32 } 33 if (tot>=ans) return; 34 for (RG int i=1;i<=b;++i) 35 for (RG int j=1;j<=c;++j) e[i][j]+=d[pos(x,i,j)]; 36 dfs(x+1,tot); 37 for (RG int i=1;i<=b;++i) 38 for (RG int j=1;j<=c;++j) e[i][j]-=d[pos(x,i,j)]; 39 if (sz[x]) dfs(x+1,tot+1); return; 40 } 41 42 il void work(){ 43 a=gi(),b=gi(),c=gi(),memset(d,0,sizeof(d)),memset(sz,0,sizeof(sz)); 44 if (a<=b && a<=c){ 45 for (RG int i=1;i<=a;++i) 46 for (RG int j=1;j<=b;++j) 47 for (RG int k=1;k<=c;++k) d[pos(i,j,k)]=gi(); 48 } else if (b<=a && b<=c){ 49 swap(a,b); 50 for (RG int i=1;i<=b;++i) 51 for (RG int j=1;j<=a;++j) 52 for (RG int k=1;k<=c;++k) d[pos(j,i,k)]=gi(); 53 } else{ 54 swap(a,c); 55 for (RG int i=1;i<=c;++i) 56 for (RG int j=1;j<=b;++j) 57 for (RG int k=1;k<=a;++k) d[pos(k,j,i)]=gi(); 58 } 59 for (RG int i=1;i<=a;++i) 60 for (RG int j=1;j<=b;++j) 61 for (RG int k=1;k<=c;++k) sz[i]+=d[pos(i,j,k)]; 62 ans=1<<30,dfs(1,0),printf("%d\n",ans); return; 63 } 64 65 int main(){ 66 #ifndef ONLINE_JUDGE 67 freopen("clear.in","r",stdin); 68 freopen("clear.out","w",stdout); 69 #endif 70 RG int T=gi(); 71 while (T--) work(); 72 return 0; 73 }