链接:https://ac.nowcoder.com/acm/contest/4784/A
来源:牛客网
牛牛最近在玩一款叫做《膜法记录》的游戏,这个游戏的机制是这样的:
在一局游戏中,所有的敌人都排布在一个 n 行 m 列的网格中,牛牛指挥着他的魔法少女对敌人进行攻击。
攻击有两种类型:行blast,列blast
行blast能消灭一整行的敌人,列blast能消灭一整列的敌人
牛牛总共能够释放 a 次行blast,b 次列blast
给定某局游戏的初始局面,请问牛牛能否将敌人全歼?
输入描述:
第一行包含一个正整数T{T}T,表示测试数据组数,接下来是T{T}T组测试数据
每组测试数据的第一行有四个正整数 n,m,a,b
接下来有n行,每行是一个长度为m的字符串,第i行第j列的字符如果是*则说明这里有一个敌人,如果是.说明这里没有
输出描述:
对每组测试数据输出一行,如果能消灭所有的敌人,就输出yes,否则输出no
示例1
备注:
题目大意:
就是你有a次行操作(可以消灭一行中的敌人)和b次列操作(可以消灭一列中的敌人),
问就是在a次行操作和b次列操作后,是否可以把n行m列的敌人全消灭掉
思路:
可以看到n的范围很小,可以二进制枚举行,让他正好消灭a行然后再判断列是否满足条件
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e5+100; int t; int n,m,a,b; char mp[100][maxn]; int main(){ cin>>t; while(t--){ cin>>n>>m>>a>>b; for(int i=0;i<n;i++){ scanf("%s",mp[i]); } int ok=0; for(int i=0;i<(1<<n);i++){//枚举行 int cnt=0; for(int j=0;j<n;j++){ if((i>>j)&1){ cnt++; } } if(cnt!=a){//如果有其他的可以那么都用完a行也能用完 continue; } int x=0; for(int j=0;j<m;j++){//枚举这一列行经过行操作还有没有敌人 int flag=0; for(int k=0;k<n;k++){ if(!((i>>k)&1) && mp[k][j]=='*'){//有敌人 flag=1; break; } } if(flag){ x++; } } if(x<=b){ ok=1; break; } } if(ok){ cout<<"yes"<<endl; } else{ cout<<"no"<<endl; } } }
dfs:
#include<stdio.h> #include<algorithm> #include<string.h> #include<set> using namespace std; int t,n,m,a,b,i,j,flag; char s[6][100005]; int vis[6]; int judge(){ set<int>q; for(i=0;i<n;i++){ if(vis[i]) continue; else{ for(j=0;j<m;j++){ if(s[i][j]=='*'){ q.insert(j); } } } } return q.size()<=b; } void dfs(int num,int aa){ if(judge()){ flag=1; return; } if(num>=n || aa>=a || flag){ return; } vis[num]=1; dfs(num+1,aa+1); vis[num]=0; dfs(num+1,aa); } int main() { scanf("%d",&t); while(t--){ memset(vis,0,sizeof(vis)); memset(s,'