【问题】
最近在生物实验室工作的小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)需要被消毒。
【输出】
仅包含D行,每行一个整数,表示对应实验皿最少要用多少单位 的F试剂。
【样例】
C.in C.out
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 3
【解释】
对于区域(1,1,3)-(2,2,4)0和(1,1,1)-(4,4,1)消毒,分别花费2个单位和1个单位的F试剂。
【限定】
输入保证满足a*b*c≤5000,T≤3。
bzoj3140 hnoi2013
不知道今天怎么了,看什么都能暴力出奇迹,事实证明我赢了。
我们只看花费为1的方案,发现有3种,而其他方案不过是若干个这种单位方案的组合。
想到这里不难看出每个点有3种方法可以消灭它,所以问题就变成了选若干种方案来消灭所有点。
由于答案不会超过min(x,y,z)所以也就不可能过20,这样我们可以直接枚举每个方案选还是不选,加一些优化答案也就能跑出来了。
有可能会爆2组但真正考试的时候,我们将会有更多时间做其他题,这20分实际上可以放弃。确实要做,也能拿这个当暴力。
代码如下:(注意优化的地方)
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=5005;
struct shu
{
int v[maxn],tot;
friend bool operator <(shu a,shu b)
{
return a.tot>b.tot;
}
}a[maxn];
int num,ans,vis[maxn],x,y,z;
void init(){
int id;
num=0;
scanf("%d%d%d",&x,&y,&z);
ans=min(x,min(y,z));
for(int i=1;i<=x+y+z;i++)
a[i].tot=0;
for(int i=1;i<=x;i++)
for(int j=1;j<=y;j++)
for(int k=1;k<=z;k++)
{
scanf("%d",&id);
if(id)
{
num++;
a[i].v[++a[i].tot]=num;
a[x+j].v[++a[x+j].tot]=num;
a[x+y+k].v[++a[x+y+k].tot]=num;
}
}
}
void run(int i,int t,int tt)
{
if(t>=ans) return;
if(tt==num) {ans=t;return;}
if(i>x+y+z) return;
if(a[i].tot*(ans-t)<=num-tt) return;
int ok=0;
for(int k=1;k<=a[i].tot;k++)if(!vis[a[i].v[k]])
{
ok++;
vis[a[i].v[k]]=i;
}
if(ok>0)
{
run(i+1,t+1,tt+ok);
for(int k=1;k<=a[i].tot;k++)if(vis[a[i].v[k]]==i)
vis[a[i].v[k]]=0;
}
run(i+1,t,tt);
}
int main()
{
//freopen("C.in","r",stdin);
//freopen("C.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
init();
if(num==x*y*z) printf("%d\n",ans);
else
{
sort(a+1,a+x+y+z+1);
memset(vis,0,sizeof(vis));
run(1,0,0);
printf("%d\n",ans);
}
}
return 0;
}