[HNOI2013]消毒
壹、题目
贰、思考
每次消毒使用 \(\min\{x,y,z\}\) 单位的药,只需要让其中一个是 \(1\),剩下的取最大?似乎可以?
或者从简单想起,从低维想。
2.1.一维弱化版
直接输出 \(1\) 的个数。
2.2.二维弱化版
矩阵是 \(n\times m\) 的。
贪心地,消毒一定选择 \(\{1,m\}\) 或者 \(\{n,1\}\),从几何上来看,就是清空一行或者一列。
如果有一个点 \((x,y)\) 需要消毒,那么一定是 \(x\) 或者 \(y\) 或者两排一起消。进一步推到:如果有一个点 \((x,y)\) 需要消毒,那么就从 \(x\rightarrow y\),然后求最小点覆盖(最大匹配)。
2.3.三维原版
实验室尺寸是 \(a\times b\times c\) 的。
继承二维,贪心地说,我们每次清空一个面,如果一个点需要清空,那么一定是三个面中的一个,一个点需要涉及三个面?这个怎么做?
注意到 \(\mathcal a\times b\times c\le 5000\),那么一定有 \(\min\{a,b,c\}\le 17\).
布吉岛怎么用......
叁、题解
好吧,直接暴力我佛了。
用 \(2^{\rm min}\) 枚举最小的那一维的每一层是消毒还是不消毒,剩下的就是二维上的问题了。
肆、代码
using namespace Elaina;
const int maxn=5e3;
const int inf=maxn+5;
int cnt;
int pos[4][maxn+5];
int a,b,c,minn;
int ans;
inline void input(){
cnt=0,ans=inf;
a=readin(1),b=readin(1),c=readin(1);
minn=Min(a,Min(b,c));
rep(i,1,a)rep(j,1,b)rep(k,1,c){
if(!readin(1))continue;
++cnt;
pos[1][cnt]=i;
pos[2][cnt]=j;
pos[3][cnt]=k;
}
if(minn==b)swap(a,b),swap(pos[1],pos[2]);
else if(minn==c)swap(a,c),swap(pos[1],pos[3]);
}
struct edge{int to,nxt;}e[maxn*maxn+5];
int tail[maxn+5],ecnt;
inline void add_edge(const int u,const int v){
e[++ecnt]=edge{v,tail[u]};tail[u]=ecnt;
}
inline void build(const int s){
memset(tail+1,0,b<<2);ecnt=0;
for(int i=1;i<=cnt;++i)if(!((s>>(pos[1][i]-1))&1))
add_edge(pos[2][i],pos[3][i]);
}
int vis[maxn+5],match[maxn+5];
int hungary(const int u){
for(int i=tail[u],v;i;i=e[i].nxt)if(!vis[v=e[i].to]){
vis[v]=1;
if(!match[v] || hungary(match[v])){
match[v]=u;
return 1;
}
}
return 0;
}
int Ans;
inline int count(int s){
int ret=0;
for(;s;s>>=1)ret+=(s&1);
return ret;
}
inline void work(const int s){
build(s);
int ans=count(s);
memset(match+1,0,c<<2);
for(int i=1;i<=b;++i){
memset(vis+1,0,c<<2);
if(hungary(i))++ans;
}
Ans=Min(Ans,ans);
}
signed main(){
rep(i,1,readin(1)){
input();Ans=inf;
for(int i=0;i<(1<<a);++i)
work(i);
writc(Ans,'\n');
}
return 0;
}
肆、用到の小 \(\tt trick\)
遇到类似 \(\prod_{i=1}^na_i\le x\),那么需要意识到 \(\min\{a_i\}\le \sqrt[n]{x}\),类似地,遇到 \(\sum_{i=1}^na_i\le x\),就有 \(min\{a_i\}\le {x\over n}\).
从简单想起,遇到高维情况,或者其他较为复杂的情况,可以考虑先简化一下问题,去掉一些限制或者降维思考,然后逐渐增加限制.
还有就是这种二分图匹配的类型,由于点必须被消毒,那么就要求对于一个点 \((x,y,z)\) 一定会选择至少一维作为消毒对象,这可以转化为最小点覆盖进而求最大匹配.

浙公网安备 33010602011771号