D—医生
本人是小白,赛时D题卡了,赛后看的@Silencer76大佬的题解,可以去看他的原题解(在吐槽区),本小白只是将他的代码转成c++(AI转的,小白不懂Python),花了好久才理解。大佬勿喷 ( ┭┮﹏┭┮ )
代码写了非常详细的注释,面向像我一样的小白。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int t,n,m,k;
map<string, int> d;
void check(vector<bool>& b, vector<string>& c)
{
string s(m,'0');//s用来记录这种药品搭配可以治愈什么类型的疾病
int cnt=0;//用药数量
for(int i=0;i<k;i++)
{
if(b[i])//如果选了第i种药
{
cnt++;//用药数量+1
for(int j=0;j<m;j++)//遍历这种药物,找出这种药物可以治愈哪些部位的疾病
{
if(c[i][j]=='1')//c存的是药
s[j]='1';//第j位置的病可以治愈
}
}
if(d.find(s)!=d.end())//如果之前已经有了相同的 能够治愈的部位的方案,取最小
d[s]=min(d[s],cnt);
else
d[s]=cnt;//没有就记录
}
}
void dfs(vector<bool>& b, vector<string>& c, int x)
{
if(x==k)//遍历完了所有药,检查这种药品的搭配可以治愈哪些部位的疾病
{
check(b,c);
return ;
}
else
{
b[x]=true;//选第x种药
dfs(b,c,x+1);
b[x]=false;//不选第x种药
dfs(b,c,x+1);
}
}
void solve(){
cin>>n>>m;
vector<string> a(n);
for(int i=0;i<n;i++)
cin>>a[i];
cin>>k;
vector<string> c(k);//c存药
vector<bool> b(k,false);//标记第 i 种药是否选择
for(int i=0;i<k;i++)
cin>>c[i];
dfs(b,c,0);//dfs搜索这 K 种药物可以有多少种搭配方案,得出每种搭配方案对应的 所能治愈的部位 以及 最小的用药数量
for(int i=0;i<n;i++)
{
int ans=100;
for(auto it:d)//从d里面取元素,看看这些不同的搭配是否可以治愈第 i 个人的所有部位的疾病
{
string temp=it.first;//这种搭配可以治愈的部位(1表示可以治愈,0表示不行)
bool sign=1;
int cnt=it.second;//用药数量
for(int j=0;j<m;j++)
{
if(a[i][j]=='1' && temp[j]=='0')//如果这个人的第 j 个部位有病,但是这种搭配不能治愈这个部位(0表示这种方案不能治愈的部位),
{ //那么这种搭配方案就不行,直接退出循环,看看下一种搭配方案是否可行
sign=0;
break;
}
}
if(sign)//取最小值
ans=min(ans,cnt);
}
if(ans==100)//ans没有被更改过,就说明所有的搭配都不能治愈这个人(可怜┭┮﹏┭┮)
cout<<-1<<"\n";
else
cout<<ans<<"\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
t=1;
//cin>>t;
while(t--){
solve();
}
return 0;
}