问题 C: Blocks(dfs)

题目描述:

给定四组字母以及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;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值