[题]虫食算 —— YbtOJ-高效进阶2021-「基础算法」第4章 深度搜索-【例题3】

在这里插入图片描述
在这里插入图片描述

心累,,、数独那道题太搞人了,硬是要二进制优化才能过……
相比之下这道题简单多了
主要思路:

  1. 先记录有多少个未知字母
  2. 按照从个位到高位,从被减数、减数、差的顺序去枚举
  3. 然后是按照得到的字母顺序去从0~n猜哪个字母是哪个数字
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100;
int tot, n, num[N], used[N], vis[N];
char  s[4][N], ch[N];
bool ck() {
	int x = 0;
	for(int i = n; i >= 1; i --) {
		int a = num[s[1][i] - 'A'],
			b = num[s[2][i] - 'A'],
			c = num[s[3][i] - 'A'];
		if(a != -1 && b != -1 && c != -1) {//某一列竖式上的三个数都确定了 
			if(x != -1) {//能确定进位  
				if((a + b + x) % n != c) return 0;//不匹配 
				if(i == 1 && a + b + x >= n) return 0;//最高位还有进位?pass!
				x = (a + b + x) / n;
			}
			else {//不完全知道,只能去猜 
				if((a + b) % n != c && (a + b + 1) % n != c)//进位只可能是0或1, 若两种可能都不满足就舍弃。 
					return 0;
				if(i == 1 && a + b >= n)//最高位还有进位,舍弃。 
					return 0;
			}
		}
		else x = -1;
	}
	return 1;
}
bool dfs(int x) {
	if(x == tot + 1) return 1;
	for(int i = 0; i < n; i ++)//n进制猜数 
		if(!used[i]) {
			num[ch[x] - 'A'] = i;
			used[i] = 1;
			if(ck() && dfs(x + 1)) return 1;//没问题就会一直返回。 
			num[ch[x] - 'A'] = -1;
			used[i] = 0;
		}
	return 0;
}
int main() {
	memset(num, -1, sizeof num);
	scanf("%d", &n);
	for(int i = 1; i <= 3; i ++)
		scanf("%s", s[i] + 1);
	for(int j = n; j >= 1; j --)//这里有个小小的顺序:先将个位上的字母进队。 
		for(int i = 1; i <= 3; i ++)
			if(!vis[s[i][j] - 'A']) {
				vis[s[i][j] - 'A'] = true;
				ch[++ tot] = s[i][j];//ch数组记录有多少种不同的字母 
			}
	dfs(1);
	for(int i = 0; i < n; i ++)
		printf("%d ",num[i]);
	puts("");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值