3140:[HNOI2013]消毒 - BZOJ

题目描述 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左右
然后开始枚举,但是还是很吃力所以对于把一个数组重新赋值的事最好避免

 

  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.
View Code

 

posted @ 2014-03-05 14:32  Randolph87  阅读(390)  评论(0编辑  收藏  举报