题目只是保证有解,交互库是自适应的,说明我们得找出最优解。
常用的二进制分组,组合数分组,说白了都是每个结果唯一对应一个答案,并根据对应方式安排询问。
这道题保证有解,就说明最终死亡数不超过 m − k m-k m−k 的所有情况总数至少为 n n n 。我们可以将这些方案与 n n n 瓶药对应起来。假设第 i i i 瓶药对应的情况是 { t 0 , t 1 , . . . , t m } \{t_0,t_1,...,t_m\} {t0,t1,...,tm}( t j t_j tj 表示第 j j j 只白鼠最早在第 t j t_j tj 轮实验挂掉(如果最终挂掉的话)),那么我们在第 t j t_j tj 轮实验时给 j j j 喂第 i i i 瓶药(前提是这时候 j j j 没死)。
可以发现最终结果一定是对应正确的毒药的。
预处理每一种情况时可以用dfs+哈希。
时间复杂度 O ( n m t ) O(nmt) O(nmt) 。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma GCC optimize(2)
using namespace std;
namespace ME{
#define MAXN 10005
#define LL long long
#define ULL unsigned LL
#define DB double
#define lowbit(x) (-(x)&(x))
#define ENDL putchar('\n')
#define FI first
#define SE second
#define PR pair<int,int>
inline int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos=0,len=fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
// #define getchar() xchar()
inline LL read() {
LL f=1,x=0;int s=getchar();
while(s<'0'||s>'9') {if(s<0)return -1;if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9') {x = (x<<3)+(x<<1)+(s^48);s=getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x=-x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,k;
int t;
int ar[MAXN][16][16],p[16][16],cnt;
map<ULL,int> mp;
void dfs(int x,int ct) {
if(ct > m-k) return ;
if(cnt >= n) return ;
if(x == m) {
ULL hs = 0;
for(int i = 0;i < t;i ++) {
for(int j = 0;j < m;j ++) {
ar[cnt][i][j] = p[i][j];
hs = hs*37 + (p[i][j]+5);
}
}
mp[hs] = cnt; cnt ++;
return ;
}
dfs(x+1,ct);
for(int i = 0;i < t && cnt < n;i ++) {
p[i][x] = 1;
dfs(x+1,ct+1);
p[i][x] = 0;
}
return ;
}
}
#include"poison.h"
int solve(int N,int M,int K,int T)
{
ME::n=N;ME::m=M;ME::k=K;ME::t=T;
ME::dfs(0,0);
bool f[20] = {};
ULL hs = 0;
for(int i = 0;i < T;i ++) {
for(int x = 0;x < N;x ++) {
for(int j = 0;j < M;j ++) {
if(!f[j] && ME::ar[x][i][j]) {
feed(x,j);
}
}
}
int S = done();
for(int j = 0;j < M;j ++) {
int nw = 0;
if(!f[j] && !(S>>j&1)) {
nw = 1; f[j] = 1;
}
hs = hs*37 + (nw+5);
}
}
return ME::mp[hs];
}