【YbtOJ高效进阶 深搜-3】【luogu P1092】虫食算

链接

YbtOJ高效进阶 深搜-3
luogu P1092

题目描述

有三个字符串,现在这三个字符串用一些大写字母代替,每个字母代表一个数字,相同的字母为相同的数字,现在要给出每个字母对应的数字,使得加法成立
字母是按A往后去计,有多少个字母就是多少进制

输入

5
ABCED
BDACE
EBBAA

输出

1 0 3 4 2

思路

考虑深搜,枚举每一个字母可能对应的数字
然后剪枝
t t t为上一位加完之后的进位
那么很显然
若满足 a + b + t ≠ c a+b+t \neq c a+b+t=c则显然当前枚举情况是错误的
若满足当前是最后一位且 a + b > n a+b>n a+b>n那么肯定也是错的,因为最高只有n位,不可能进位
因为是加法, 那么进位仅可能是0或1
那么如果满足 a + b ≠ c a+b \neq c a+b=c a + b + 1 ≠ c a+b+1 \neq c a+b+1=c那么当前情况也是错误的
因此得到剪枝的策略,直接深搜就可以了

代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int n, num;
int shu[105], used[555], chi[1005];
char vis[1005], s[55][1005];

bool check() {
    
    
    int x = 0;
    for (int i = n; i >= 1; --i) {
    
    
        int a = shu[s[1][i] - 'A'];
        int b = shu[s[2][i] - 'A'];
        int c = shu[s[3][i] - 'A'];
        if (a != -1 && b != -1 && c != -1) {
    
    
            if (x != -1) {
    
    
                if ((a + b + x) % n != c)
                    return 0;//如上情况1
                if (i == 1 && a + b + x >= n)
                    return 0;//如上情况2
                x = (a + b + x) / n;
            } else {
    
    
                if ((a + b) % n != c && (a + b + 1) % n != c)//如上情况3
                    return 0;
                if (i == 1 && a + b >= n)
                    return 0;
            }
        } else
            x = -1;
    }
    return 1;
}

bool dfs(int x) {
    
    
    if (num + 1 == x)
        return 1;
    for (int i = 0; i < n; ++i)
        if (!used[i]) {
    
    
            used[i] = 1;
            shu[chi[x] - 'A'] = i;
            if (check() && dfs(x + 1))
                return 1;
            shu[chi[x] - 'A'] = -1;
            used[i] = 0;
        }//模拟每一个字母
    return 0;
}

int main() {
    
    
    memset(shu, -1, sizeof(shu));
    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'] = 1;
                chi[++num] = s[i][j];
            }//记录出现了那些字母
    dfs(1);
    for (int i = 0; i < n; ++i) printf("%d ", shu[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/112427536