P1092 虫食算

题目传送:https://www.luogu.org/problem/show?pid=1092

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define maxn 30
int n,flag[maxn];
char s[4][maxn];
bool use[maxn];
int id(char ch)//将字符串转换为数字
{
    return ch-‘A‘+1;
}
void dfs(int x,int y,int t)//x代表列,y代表行,t代表进位
{
    if (x==0) //从上到下,从右到左,x==0表示搜到了最后一列
    {
        if (t==0)//最后一列不能有进位,如果进了以为则第三个字符串会比其他两个字符串长一位
        {
            for (int i=1;i<n;i++) //如果满足条件,就输出
                printf("%d ",flag[i]);//输出
            printf("%d\n",flag[n]);//输出
            exit(0);    //相当于return  0;程序结束
        }
        return;//返回
    }
    for (int i=x-1;i>=1;i--) //剪枝1
    {
        int w1=flag[id(s[1][i])];//w1表示第一行字符串代表的数字
        int w2=flag[id(s[2][i])];//w2表示第二行字符串代表的数字
        int w3=flag[id(s[3][i])];//w3表示第三行字符串代表的数字
        if (w1==-1||w2==-1||w3==-1) //如果这个位置上还没被赋值,就返回
            continue;
        if ((w1+w2)%n!=w3&&(w1+w2+1)%n!=w3)
            return;    //如果无论进位与否,都不能整除对应的w3就说明字符串不匹配,直接return ;
    }
    if (flag[id(s[y][x])]==-1) ////如果这个位置上还没被赋值,就进行赋值操作
    {

        for (int i=n-1;i>=0;i--) //倒着枚举更快
            if (!use[i]) //如果这个数没有用过
            {
                if (y!=3) //且不是最后一行
                {
                    flag[id(s[y][x])]=i;//就将这个位置赋上值
                    use[i]=1;//标记这个数用过
                    dfs(x,y+1,t);//继续搜索下一行
                    flag[id(s[y][x])]=-1;//还原
                    use[i]=0;//还原
                }
                else //当y==3时
                {
                    int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t;//两个数加上它们的进位
                    if (w%n!=i)
                        continue;
                    use[i]=1;flag[id(s[3][x])]=i;//赋值,标记这个数用过
                    dfs(x-1,1,w/n);//搜索下一列,进位需要改变
                    use[i]=0;flag[id(s[3][x])]=-1;//还原
                }
            }
    }
    else //如果这个位置上已经被赋值了
    {
        if (y!=3) //继续搜索
            dfs(x,y+1,t);
        else
        {
            int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t;
            if (w%n!=flag[id(s[3][x])]) //剪枝 2
                return;
            dfs(x-1,1,w/n);//搜索下一列,进位需要改变
        }
    }
}
int main()
{
    scanf("%d",&n);//读入n,代表n进制等......
    for (int i=1;i<=3;i++)
        scanf("%s",s[i]+1);//读入3行字符串
    memset(flag,-1,sizeof(flag));//将所有位置标记为未赋值
    dfs(n,1,0);//从右往左,上往下搜索,所有从第n列,第1行开始
    return 0;//结束
}
时间: 2024-10-20 14:03:57

P1092 虫食算的相关文章

洛谷 P1092 虫食算

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

Luogu P1092 虫食算(枚举+剪枝)

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

[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位,允许有前

洛谷 P1092 虫食算 Label:dfs

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

Luogu P1092 虫食算

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

洛谷P1092虫食算——深搜

题目:https://www.luogu.org/problemnew/show/P1092 剪枝1:从右往左.从上往下按字母出现顺序搜索: 剪枝2:同一列前两个数字确定,可直接算出第三个数字并判断: 剪枝3:每次搜索前看看前面的列上有没有已经不符合的情况(进位最多为1): 代码如下: #include<iostream> #include<cstdio> using namespace std; int n,c[300],jin[30]; char a[5][30]; bool

LUGOU P1092 虫食算

传送门 解题思路 刚开始按yzy神犇给的方法写,就是每次要把能算出来的都算出来,结果因为太菜写挂了..后来直接爆搜水过.. #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> using namespace std; const int MAXN=40; int n,a[MAXN],cnt; char s[4][MAXN];

P1092虫食算题解

2018-10-24 题目链接 题目思路: 我就讲下剪枝操作吧. 三个式子从上到下为A,B,C 剪枝操作 1.从3个式子右边开始从上到下枚举字母对应数字.(搜索顺序关键) 2.末尾(A+B)%n!=C. 3.已知A,B,不知C,且C的可能数字已经使用.(这三个点从2000ms) 4.已知A.C,不知B,且B的可能数字已经使用.(一下剪枝成) 5.已知B,C,不知A,且A的可能数字已经使用.(100ms) 6.已知A,B,C,且A+B不等于C,且A+B+1不等于C. 7.已经A,B,C的最高位,且