问个问题
查看原帖
问个问题
389476
lrt_2008楼主2021/8/20 17:39
#include<bits/stdc++.h>
using namespace std;
#define M 30
int n,flag[M];
char s[4][M];
bool use[M];
int id(char ch)
{
    return ch-'A'+1;
}
void dfs(int x,int y,int t)
{
    if(x==0)
    {
        if(t==0)
        {
            for(int i=1;i<n;i++)//如果满足条件,就输出
                cout<<flag[i]<<' ';
            cout<<flag[n]<<'\n';
            exit(0);//程序结束
        }
        return;//返回
    }
    for(int i=x-1;i>=1;i--)//可行性剪枝
    {
        int w1=flag[id(s[1][i])];//第一行字符串代表的数字
        int w2=flag[id(s[2][i])];//第二行字符串代表的数字
        int w3=flag[id(s[3][i])];//第三行字符串代表的数字
        if(w1==-1||w2==-1||w3==-1) //如果这个位置上还没被赋值,就寻找下一位
            continue;
        if((w1+w2)%n!=w3&&(w1+w2+1)%n!=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//如果是最后一行
                {
                    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])])//可行性剪枝
                return;
            dfs(x-1,1,w/n);//搜索第一列,进位需要改变
        }
    }
    return ;//结束搜索
}
int main()
{
    ios::sync_with_stdio(false);
    scanf("%d",&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;//AC代码
}

为什么并须用scanf读取n才能对

2021/8/20 17:39
加载中...