洛谷 P1092 虫食算(dfs)

题目传送

这题的官方题解是高斯消元,可是本蒟蒻不会。。。

讲一下深搜的方法:
1.搜索从第一位的值开始搜,直到最后一位,判断是否合法。
2.注意剪枝防TLE。
3.三个数都是n位,最高位不能有进位。

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn = 30;

int n;
int ans[maxn]; //赋值
char ss[4][maxn];
bool used[maxn];

int toid(char ch)
{
	return ch - 'A' + 1;
}

void dfs(int x, int y, int t) //列,行,进位
{
	if (!x) {
		if (!t) { //最高位不能有进位
			for (int i = 1; i <= n; i++) cout << ans[i] << " ";
			exit(0); //相当于return 0 结束程序
		}
		return;
	}
	for (int i = x - 1; i > 0; i--) { //剪枝
		int w1 = ans[toid(ss[1][i])];
		int w2 = ans[toid(ss[2][i])];
		int w3 = ans[toid(ss[3][i])];
		if (w1 == -1 || w2 == -1 || w3 == -1) continue; //未赋值
		if ((w1 + w2) % n != w3 && (w1 + w2 + 1) % n != w3) return; //无论进不进位都不成立
	}
	if (ans[toid(ss[y][x])] == -1) { //未赋值
		for (int i = n - 1; i >= 0; i--) {
			if (!used[i]) { //未使用
				if (y == 3) {  //第三行
					int w = ans[toid(ss[1][x])] + ans[toid(ss[2][x])] + t;
					if (w % n != i) continue;
					used[i] = 1;
					ans[toid(ss[3][x])] = i; //将该字母赋为i
					dfs(x - 1, 1, w / n); //处理下一列
					used[i] = 0; //回溯
					ans[toid(ss[3][x])] = -1;
				}
				else {
					used[i] = 1;
					ans[toid(ss[y][x])] = i;
					dfs(x, y + 1, t); //处理下一行
					used[i] = 0;
					ans[toid(ss[y][x])] = -1;
				}
			}
		}
	}
	else {
		if (y == 3) {
			int w = ans[toid(ss[1][x])] + ans[toid(ss[2][x])] + t;
			if (w % n != ans[toid(ss[3][x])]) return;
			dfs(x - 1, 1, w / n);
		}
		else dfs(x, y + 1, t);
	}
}

int main(void)
{
	cin >> n;
	memset(ans, -1, sizeof(ans));
	for (int i = 1; i <= 3; i++) cin >> ss[i] + 1;
	dfs(n, 1, 0); //从第n列第1行开始搜
	return 0;
}
发布了30 篇原创文章 · 获赞 50 · 访问量 5290

猜你喜欢

转载自blog.csdn.net/qq_43054573/article/details/104674316