题目描述 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 Description
输入文件第一行是一个正整数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。
输出描述 Output Description
仅包含 D 行,每行一个整数,表示对应实验皿最少要用多少单位的 F 试剂。
样例输入 Sample Input
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
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
对于区域(1,1,3)-(2,2,4)和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。
终于过了,fillchar没有一点优势啊
还是用各种for来把赋初值快一些
二维的怎么做大家都知道,就是二分图匹配,但是这是三维
怎么办呢?
!!!!强行转化成二维,枚举第三维的情况,那这需要2^k所以我们找最小的k
因为a*b*c<=5000,所以min{a,b,c}最大是17左右
然后开始枚举,但是还是很吃力所以对于把一个数组重新赋值的事最好避免
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 var 2 f:array[0..5000,1..3]of longint; 3 first,next,last,cover,bool:array[0..5000]of longint; 4 flag,sum:array[0..20]of boolean; 5 a,b,c,tot,num,min,aug,ans,match,t,time,time2,maxa,maxb,maxc:longint; 6 7 procedure swap(var x,y:longint); 8 var 9 t:longint; 10 begin 11 t:=x; 12 x:=y; 13 y:=t; 14 end; 15 16 procedure init; 17 var 18 i,j,k,s,ai,bi,ci:longint; 19 begin 20 read(ai,bi,ci); 21 a:=1; 22 b:=2; 23 c:=3; 24 num:=0; 25 maxa:=0; 26 maxb:=0; 27 maxc:=0; 28 for i:=1 to ai do 29 for j:=1 to bi do 30 for k:=1 to ci do 31 begin 32 read(s); 33 if s=1 then 34 begin 35 inc(num); 36 f[num,1]:=i; 37 f[num,2]:=j; 38 f[num,3]:=k; 39 if i>maxa then maxa:=i; 40 if j>maxb then maxb:=j; 41 if k>maxc then maxc:=k; 42 end; 43 end; 44 min:=ai; 45 if bi<min then min:=bi; 46 if ci<min then min:=ci; 47 if (bi<=ai)and(bi<=ci) then 48 begin 49 swap(a,b); 50 swap(maxa,maxb); 51 end 52 else 53 if (ci<=ai)and(ci<=bi) then 54 begin 55 swap(a,c); 56 swap(maxa,maxc); 57 end; 58 fillchar(sum,sizeof(sum),false); 59 for i:=1 to num do 60 sum[f[i,a]]:=true; 61 end; 62 63 function path(x:integer):boolean; 64 var 65 i:integer; 66 begin 67 i:=first[x]; 68 while i<>0 do 69 begin 70 if bool[last[i]]<>time2 then 71 begin 72 bool[last[i]]:=time2; 73 if (cover[last[i]]=0)or(path(cover[last[i]])) then 74 begin 75 cover[last[i]]:=x; 76 exit(true); 77 end; 78 end; 79 i:=next[i]; 80 end; 81 exit(false); 82 end; 83 84 procedure insert(x,y:integer); 85 begin 86 inc(tot); 87 last[tot]:=y; 88 next[tot]:=first[x]; 89 first[x]:=tot; 90 end; 91 92 procedure work; 93 var 94 i:integer; 95 begin 96 if aug>ans then exit; 97 tot:=0; 98 match:=0; 99 for i:=1 to maxb do 100 first[i]:=0; 101 for i:=1 to maxc do 102 cover[i]:=0; 103 for i:=1 to num do 104 if flag[f[i,a]] then insert(f[i,b],f[i,c]); 105 for i:=1 to maxb do 106 begin 107 inc(time2); 108 if path(i) then inc(match); 109 end; 110 if ans>aug+match then ans:=aug+match; 111 end; 112 113 procedure try(x:integer); 114 begin 115 if x>min then work 116 else 117 begin 118 flag[x]:=true; 119 try(x+1); 120 if sum[x] then 121 begin 122 flag[x]:=false; 123 inc(aug); 124 try(x+1); 125 dec(aug); 126 end; 127 end; 128 end; 129 130 begin 131 read(t); 132 for time:=1 to t do 133 begin 134 init; 135 ans:=200; 136 try(1); 137 writeln(ans); 138 end; 139 end.