luogu_P1092 虫食算

https://www.luogu.org/problem/P1092

所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

 43#9865#045
+  8468#6633
 44445509678

其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是55和33,第二行的数字是55。

现在,我们对问题做两个限制:

首先,我们只考虑加法的虫食算。这里的加法是NN进制加法,算式中三个数都有NN位,允许有前导的00。

其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是NN进制的,我们就取英文字母表午的前NN个大写字母来表示这个算式中的00到N-1N−1这NN个不同的数字:但是这NN个字母并不一定顺序地代表00到N-1N−1。输入数据保证NN个字母分别至少出现一次。

 BADC
+CBDA
 DCCC

上面的算式是一个4进制的算式。很显然,我们只要让ABCDABCD分别代表01230123,便可以让这个式子成立了。你的任务是,对于给定的NN进制加法算式,求出NN个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。

输入格式

包含四行。
第一行有一个正整数N(N \le 26)N(N≤26)。

后面的三行,每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有NN位。

输出格式

一行,即唯一的那组解。

解是这样表示的:输出NN个数字,分别表示A,B,C,…A,B,C,…所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。



按从小位到大位,上到下枚举每一个点

但是不吸氧会T一个点

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

#define ri register int
#define u int

using std::cin;
using std::string;

namespace all {

    u N,ans[30],vt[30],j[30],s[4][30];
    string a,b,c;

    u dfs(const u &x,const u &k) {
        for(ri i(1);i<=N;++i){
            if(ans[s[1][i]]!=-1&&ans[s[2][i]]!=-1&&ans[s[3][i]]!=-1&&((((ans[s[1][i]]+ans[s[2][i]]+1)%N)^ans[s[3][i]])&&(((ans[s[1][i]]+ans[s[2][i]])%N)^ans[s[3][i]]))){
                return 0;
            }
        }
        if(x==N+1) {
            if(!j[x]) {
                for(ri i(1); i<=N; ++i) printf("%d ",ans[i]);
                exit(0);
            }
            return 0;
        }
        j[x+1]=0;
        if(ans[s[k][x]]==-1) {
            for(ri i(0); i<=N; ++i) {
                if(!vt[i]) {
                    ans[s[k][x]]=i,vt[i]=1,j[x+1]=0;
                    if(k==1) {
                        if(dfs(x,2)) return 1;
                    } else {
                        if(ans[s[3][x]]==-1) {
                            ans[s[3][x]]=ans[s[1][x]]+ans[s[2][x]]+j[x];
                            if(ans[s[3][x]]>=N) j[x+1]=1,ans[s[3][x]]%=N;
                            if(!vt[ans[s[3][x]]]) {
                                vt[ans[s[3][x]]]=1;
                                if(dfs(x+1,1)) return 1;
                                vt[ans[s[3][x]]]=0,ans[s[3][x]]=-1,j[x+1]=0;
                            } else {
                                j[x+1]=0,ans[s[3][x]]=-1;
                            }
                        } else {
                            if(ans[s[3][x]]==((ans[s[1][x]]+ans[s[2][x]]+j[x])%N)) {
                                if(ans[s[1][x]]+ans[s[2][x]]+j[x]>=N) j[x+1]=1;
                                if(dfs(x+1,1)) return 1;
                                j[x+1]=0;
                            }
                        }
                    }
                    ans[s[k][x]]=-1,vt[i]=0;
                }
            }
        } else {
            if(k==1) {
                if(dfs(x,2)) return 1;
            } else {
                if(ans[s[3][x]]==-1) {
                    ans[s[3][x]]=ans[s[1][x]]+ans[s[2][x]]+j[x];
                    if(ans[s[3][x]]>=N) j[x+1]=1,ans[s[3][x]]%=N;
                    if(!vt[ans[s[3][x]]]) {
                        vt[ans[s[3][x]]]=1;
                        if(dfs(x+1,1)) return 1;
                        vt[ans[s[3][x]]]=0,ans[s[3][x]]=-1,j[x+1]=0;
                    } else {
                        j[x+1]=0,ans[s[3][x]]=-1;
                    }
                } else {
                    if(ans[s[3][x]]==((ans[s[1][x]]+ans[s[2][x]]+j[x])%N)) {
                        if(ans[s[1][x]]+ans[s[2][x]]+j[x]>=N) j[x+1]=1;
                        if(dfs(x+1,1)) return 1;
                        j[x+1]=0;
                    }
                }
            }
        }
        return 0;
    }

    inline void solve() {
        cin>>N>>a>>b>>c;
        for(ri i(1); i<=N; ++i)s[1][i]=(u)a[N-i]-‘A‘+1;
        for(ri i(1); i<=N; ++i)s[2][i]=(u)b[N-i]-‘A‘+1;
        for(ri i(1); i<=N; ++i)s[3][i]=(u)c[N-i]-‘A‘+1;
        memset(ans,-1,sizeof(ans));
        dfs(1,1);
    }

}

int main() {

    //freopen("x.txt","r",stdin);
    all::solve();

}

原文地址:https://www.cnblogs.com/ling-zhi/p/11664847.html

时间: 2024-10-01 16:15:30

luogu_P1092 虫食算的相关文章

NOIP2004 虫食算

四.虫食算 (alpha.pas/dpr/c/cpp) [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045     +    8468#6633        44445506978 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许

69. [NOIP2004] 虫食算

69. [NOIP2004] 虫食算 ★★★   输入文件:alpha.in   输出文件:alpha.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    + 8468#6633 ----------- 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是

深度优先搜索 codevs 1064 虫食算

codevs 1064 虫食算 2004年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    +    8468#6633       44445506978 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5

noip 虫食算 (搜索)

描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子:43#9865#045+ 8468#6633= 44445506678其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制:首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字

[NOIP2004] 提高组 洛谷P1092 虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

洛谷—— P1092 虫食算

https://www.luogu.org/problem/show?pid=1092 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: http://paste.ubuntu.com/25448822/ 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前

虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

【NOIP2004】虫食算

Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +   8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的

DFS——jzyzoj1187:虫食算

卡了两天的虫食算,调了一天的错误代码.给出题面: 没错题目很长,不过实际上就是给出三个n位数的字符串,每个大写字母都代表唯一的数字,让第一个字符串与第二个字符串相加,使得前两个字符串构成的N位数字相加后等于第三个字符串所代表的N位数字.按照字典序输出各个大写字母对应的值. 暴力的方法非常简单.用简单的dfs+回溯搜索每一个大写字母出现的值然后相加(注意进制以及进位),如果最终结果符合条件的话退出即可. 代码: 1 //暴力 2 #include <iostream> 3 #include &l