popcorn(dfs,二进制记录答案)
题目来源:https://atcoder.jp/contests/abc358/tasks/abc358_c
//
题意:m种爆米花,n个店铺,每个店铺有一个m长的字符串,如果第j个字符为o,则意味着i摊位出售口味j的爆米花。问最少多少次的店铺购买,就能购买到所有种类的爆米花。
//
思路:
dfs搜索啊,把每个字符串转化为01串,然后每位进行异或运算(位运算没写出来,后面可以优化下代码,该题解是直接模拟的),然后每次新访问一个店铺后刷新状态,然后cheak(判断是否所有的爆米花都购买了)下,输出最小值cnt就可以了。
//
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=19;
vector<string>mp(19);
vector<int>vis(N,0);
vector<string>a(N);
int n,m,Min=N;
bool cheak(string s){
for(int i=0;i<m;i++){
if(s[i]=='0') return false;
}
return true;
}
void dfs(int x,string s,int cnt){//从第x个店铺开始,s:当前购买爆米花状态,在cnt个店铺买了
if(cheak(s)){
Min=min(Min,cnt);
return;
}
for(int i=x+1;i<=n;i++){
string t=s;
for(int j=0;j<m;j++){
if(s[j]=='1'&&a[i][j]=='1'){
t[j]='1';
}
else if(s[j]=='1'&&a[i][j]=='0'){
t[j]='1';
}
else if(s[j]=='0'&&a[i][j]=='1'){
t[j]='1';
}
else if(s[j]=='0'&&a[i][j]=='0'){
t[j]='0';
}
}
vis[i]=1;
cnt++;
dfs(i,t,cnt);
cnt--;
vis[i]=0;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>mp[i];
for(int t=m-1;t>=0;t--){//转为2进制
if(mp[i][t]=='o'){
mp[i][t]='1';
}
else{
mp[i][t]='0';
}
}
a[i]=mp[i];
}
//dfs()找到最少次数求得2^m
for(int i=1;i<=n;i++){
dfs(i,a[i],1);
}
cout<<Min<<endl;
return 0;
}
浙公网安备 33010602011771号