题目描述:
给定四组字母以及n个询问(每个询问是一个不超过4位的字符串),问是否能用给定的四组字母拼成这个字符串(每组每次只能使用一个字母且每组在一次询问中只能用一次)
思路:
错误思路:开始没想到dfs,试着用贪心做了一下,就是对询问中的每一个字母,从前往后遍历给定的四组字母,若碰到还未使用的某一组中存在此字母,则直接标记此组已使用并跳出,若是查询中的字母无法在任意一组找到则输出NO;
这样贪心有一个明显的漏洞,前面选的组并不一定是最优解,在后面的字母选组时会受到前面选择的干扰。
如:
1 MOOOOO OOOOOO ABCDEF UVWXYZ OMAU
就过不了。
正确思路:
错误思路里会有某些情况受前后选择的影响,那干脆所有合法情况都遍历一遍,而且数据较小,直接dfs即可。
实现代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=200010;
int tong[5][300];//第一维1--4代表了四个木块,
//第二维用来存储每个木块上有哪些字母(因为懒没做离散化直接把数组开到300)
int ans;
char as[5];
bool b[5];
void dfs(int x){//数据量很小想到dfs
if(x>=strlen(as)){
ans=1;
return ;
}
for(int j=1;j<=4;j++){
if(b[j]&&tong[j][as[x]]){
b[j]=false;
dfs(x+1);
b[j]=true;
}
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=4;i++){
char a;
for(int j=0;j<6;j++){
cin>>a;
tong[i][a]++;//统计每个方块上的字母
}
}
while(n--){
cin>>as;
ans=0;
for(int i=1;i<=4;i++) b[i]=true;//判断数组b[]的初始化
dfs(0);
if(ans==1) puts("YES");
else puts("NO");
}
return 0;
}