`
阿尔萨斯
  • 浏览: 4170546 次
社区版块
存档分类
最新评论

uva 1548 - The Game of Master-Mind(dfs+剪枝)

 
阅读更多

题目链接:uva 1548 - The Game of Master-Mind


题目大意:现在ACM公司要开发一个手游,游戏大致为猜数字,一开始给出p,c和m,p为要猜数字的个数,c为每个数字的最大上限,m为已经猜过的次数,每次猜完系统会给出相应的回复提示,所以接下来有2*m行为前m次的提示。每组提示分两行,一行是当前猜的数字分别有哪些,一行是代表说黑点个数和白点个数,所谓黑点个数即当前猜的数字有多少个与答案的位置且颜色均相同(题目中用数字代表颜色),白点则是颜色相同,位置不同的点。要注意的是黑点和白点是一一对应的,例:ans:1 1 2 guess:2 2 1,这种情况下白点个数为2,不是3,就是ans中的2只能对应guess中的一个2,而且如果是黑点的话,就不能算成是白点。现在要求说找出与答案最相近的序列,即满足先前所猜的m次的序列,并且要求字典序最小。


解题思路:dfs,不过光dfs的话,复杂度为100^10。当时因为题目中给的限定条件特别多,所以如果在过程中对黑点白点的情况进行判断,时间上是没有问题的。


但是在判断黑点和白点的时候要注意,统计时要统计黑点个数和点数总和,因为如果将黑点和白点分开计算的话会比较麻烦,因为会有说guess1:2 1,黑1,白0,这样的话ans为1 1是满足的,但是在dfs0层是,ans中的第一个1就变成了白点,如果剪枝为白点个数为0返回就错了。我的处理方法就感觉像是可以先向黑点预支一样,但是预支也有额度,如果超过现存黑点的个数也是不行的。


#include <stdio.h>
#include <string.h>

const int N = 105;
const int M = 15;

int p, c, m, b[N], w[N], ans[M];
int g[N][M], l[N][N], r[N][N];
int cnt[N], sum[N];

void init () {
	memset(l, 0, sizeof(l));
	memset(r, 0, sizeof(r));
	memset(cnt, 0, sizeof(cnt));
	memset(sum, 0, sizeof(sum));

	scanf("%d%d%d", &p, &c, &m);

	for (int i = 0; i < m; i++) {

		for (int j = 0; j < p; j++) {
			scanf("%d", &g[i][j]);
			r[i][g[i][j]]++;
		}
		scanf("%d%d", &b[i], &w[i]);
	}
}

inline bool judge (int x, int d) {
	
	for (int i = 0; i < m; i++) {
		if (x == g[i][d]) {
			if (b[i] == cnt[i]) return false;
		} else if (l[i][x] < r[i][x]) {
			if (sum[i] >= w[i] + b[i]) return false;
		}
	}
	return true;
}

inline void set (int x, int d, int flag) {

	if (flag > 0) {
		for (int i = 0; i < m; i++) {
			if (x == g[i][d])
				cnt[i]++;

			if (l[i][x] < r[i][x])
				sum[i]++;
			l[i][x]++;
		}
	} else {
		for (int i = 0; i < m; i++) {
			if (x == g[i][d])
				cnt[i]--;
			l[i][x]--;
			if (l[i][x] < r[i][x])
				sum[i]--;
		}
	}
}

bool dfs (int d) {
	if (d == p) {
		for (int i = 0; i < m; i++)
			if (cnt[i] != b[i] || sum[i] != w[i] + b[i]) return false;
		return true;
	}

	for (int i = 1; i <= c; i++) {

		if (!judge(i, d)) continue;
		set(i, d, 1);

		ans[d] = i;
		if (dfs(d+1)) return true;

		set(i, d, -1);
	}
	return false;
}

int main () {
	int cas;
	scanf("%d", &cas);
	while (cas--) {
		init ();
		bool flag = dfs(0);

		if (flag) {
			printf("%d", ans[0]);
			for (int i = 1; i < p; i++)
				printf(" %d", ans[i]);
			printf("\n");
		} else 
			printf("You are cheating!\n");
	}
	return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics