显然选择的区域有一维要是1,其他维要最大
相当于问最少切多少个面才能覆盖所有点 a*b*c<=5000 那么一定有一个小于等于17 枚举这一维切不切,跑二分图即可TLE代码千万别复制
# include# define IL inline# define RG register# define Fill(a, b) memset(a, b, sizeof(a))# define Copy(a, b) memcpy(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(5010), __(1e6 + 10);IL ll Read(){ RG char c = getchar(); RG ll x = 0, z = 1; for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z;}int a, b, c, x[_], y[_], z[_], n, ans;int fst[_], nxt[__], to[__], cnt, match[_], vis[_], id;IL void Add(RG int u, RG int v){ to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; }IL bool Dfs(RG int u){ for(RG int e = fst[u]; e != -1; e = nxt[e]){ if(vis[to[e]] == id) continue; vis[to[e]] = id; if(match[to[e]] == -1 || Dfs(match[to[e]])){ match[to[e]] = u; return 1; } } return 0;}IL int Calc(RG int S){ Fill(fst, -1); cnt = 0; Fill(match, -1); for(RG int i = 1; i <= n; ++i) if(S & (1 << (z[i] - 1))) Add(x[i], y[i]); RG int Ans = c; for(; S; S -= S & -S) --Ans; for(RG int i = 1; i <= a; ++i) ++id, Ans += Dfs(i); return Ans;}int main(RG int argc, RG char* argv[]){ RG int T = Read(); while(T--){ n = 0; a = Read(); b = Read(); c = Read(); for(RG int i = 1; i <= a; ++i) for(RG int j = 1; j <= b; ++j) for(RG int k = 1; k <= c; ++k) if(Read()) x[++n] = i, y[n] = j, z[n] = k; if(a < b && a < c){ swap(a, c); for(RG int i = 1; i <= n; ++i) swap(x[i], z[i]); } else if(b < a && b < c){ swap(b, c); for(RG int i = 1; i <= n; ++i) swap(y[i], z[i]); } ans = c; for(RG int i = 0, S = 1 << c; i < S; ++i) ans = min(ans, Calc(i)); printf("%d\n", ans); } return 0;}