ABC 356

C. Keys

 

        拿到一道题,首先先去看数据范围。n 只有 15,也就是所有的状态 2^n 可以接受,因此直接去枚举所有钥匙状态。2^15 = 3e4,2^20 = 1e6。

        通过 dfs 搜出所有状态,再去遍历 m 种已知条件,一旦出现不符合的直接返回。

        看了数据范围就会发现这道题不需要什么算法以及结论,直接暴力就可以了。 

        一个小技巧是用一个 01 字符串来表示每把钥匙的真假。 

#include
#define int long long
using namespace std;
const int N = 2e5 + 5, INF = 1e18;

int T, n, m, k, ans, c[105], a[105][20];
char ch[105];

bool check(string s)
{
	for (int i = 1; i <= m; i ++)
	{
		int cnt = 0;
		for (int j = 1; j <= c[i]; j ++)
			if (s[a[i][j]] == '1')
				cnt ++;
		if (cnt >= k && ch[i] == 'x')
			return false;
		if (cnt < k && ch[i] == 'o')
			return false;
	}
	return true;
}

void dfs(int dep, string s)
{
	if (dep > n)
	{
		if (check(s))
			ans ++;
		return;
	}
	dfs(dep + 1, s + '0');
	dfs(dep + 1, s + '1');
}

signed main()
{
	cin >> n >> m >> k;
	for (int i = 1; i <= m; i ++)
	{
		cin >> c[i];
		for (int j = 1; j <= c[i]; j ++)
			cin >> a[i][j];
		cin >> ch[i];
	}
	dfs(1, " ");
	cout << ans;
	return 0;
}

你可能感兴趣的:(算法,深度优先,图论)