【Ybtoj 第4章 例题3】虫食算【深搜】

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


解题思路

40分:暴力搜索每个字母代表的数

考虑剪枝 (搜索字母的顺序按竖式的从右到左,方便剪枝)
每搜索一个字母时,其实已经可以判断竖式的可行性了

  • 当竖式上当前位的右边都有时, ( a + b ) ( a + b ) % n < > c (a+b)不可行(加数 x , y x , y x,y z z z)。
    但是还要考虑进位,设右边进位 t t t ( a + b + t ) ( a + b+ t ) % n < > c (a+b+t)不可行
  • 当竖式上当前位的右边有字母没有搜索时,无法判断有没有进位
    但是加法中的进位最多为1,即当 ( a + b ) ( a + b ) % n < > z (a+b) ( a + b + 1 ) ( a + b + 1 ) % n < > z (a+b+1) 不可行
  • 当前位已是第一位,但是依然有进位, ( i = = 1 ) ( i = = 1 ) (i==1) ( a + b ) / n > 0 ( a + b) / n > 0 (a+b)/n>0不可行

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

bool flag=0;
int ans[50],v[50],kj[50],lyx[50],n,m;
string s[3];

bool check(){
    
    //判断可行性
	int t=0;
	for(int i=n-1; i>=0; i--)
	{
    
    
		int a=ans[s[0][i]-64],b=ans[s[1][i]-64],c=ans[s[2][i]-64];
		if(a!=-1&&b!=-1&&c!=-1)
		{
    
    
			if(t!=-1)
			{
    
    
				if((a+b+t)%n!=c)return 0;//1
				if(i==0&&(a+b+t)/n)return 0;//3
				t=(a+b+t)/n;
			}
			else
			{
    
     
				if((a+b)%n!=c&&(a+b+1)%n!=c)return 0;//1,2
				if(i==0&&(a+b)/n)return 0;//3
			}
		}
		else t=-1;//当前位有字母还没搜索,进位设为-1
	}
	return 1;
}

void dfs(int dep){
    
    
	if(flag==1)
		return;
	if(dep>n)
	{
    
    
		for(int i=1;i<=n;i++)
			printf("%d ",ans[i]);
		flag=1;
		return;
	}
	for(int i=0;i<n;i++)
	{
    
    
		if(!v[i])//搜索每个字母可用数字
		{
    
    
			v[i]=1;
			ans[lyx[dep]]=i; 
			if(check())
				dfs(dep+1);
			v[i]=0;
			ans[lyx[dep]]=-1;
		}
	}
}

int main()
{
    
    
	scanf("%d",&n);
    for(int i=0; i<=2; i++)
        cin>>s[i];
    for(int j=n-1; j>=0; j--)//从右到左
        for(int i=0; i<=2; i++)
        {
    
    
            {
    
    
                if(!v[s[i][j]-64])
                {
    
    
                	v[s[i][j]-64]=1;
                lyx[++m]=s[i][j]-64;//字母按出现顺序记录
				}
                    
            }
        }
    memset(ans,-1,sizeof(ans));
	memset(v,0,sizeof(v)); //懒得多建一个数组,重新利用
    dfs(1);
}

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/112390723