《ybtoj高效进阶》第一部分第四章例题3 虫食算&P1092

题目大意

给一组n进制加法竖式,位数必为n,可以有前导零,每个字母对应一个不同的数字,求一组解。保证有解且唯一。

思路

我们显然只能用dfs解决该题目,所以需要剪枝
剪枝1:我们模拟手动计算,如果在当前情况下已经无解马上回溯
剪枝2:因为解有且唯一,我们一旦找到解就马上输出并结束程序
code:

#include<cstdio>
#include<queue>
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
int n,tot,no[27];
bool ow,vis[27],us[27];
char o[3][27],cr[27];
bool check()
{
    
    
 int x=0;
 for (int i=n-1;i>=0;i--)
 {
    
    
  int add1=no[o[0][i]-'A'],add2=no[o[1][i]-'A'],he=no[o[2][i]-'A'];
  if (add1!=-1&&add2!=-1&&he!=-1)
  {
    
    
   if (x==-1)
   {
    
    
    if ((add1+add2)%n!=he&&(add1+add2+1)%n!=he)
    {
    
    
     return 0;
    }
    if (i==0&&add1+add2>=n)
    {
    
    
     return 0;
    }
   }
   else
   {
    
    
    if ((add1+add2+x)%n!=he)
    {
    
    
     return 0;
    }
    if ((add1+add2+x)>=n&&i==0)
    {
    
    
     return 0;
    }
    x=(add1+add2+x)/n;
   }
  }
  else x=-1;
 }
 return 1;
}
bool dfs(int x)
{
    
    
 if (x==tot)
 {
    
    
  return 1;
 }
 for (int i=0;i<n;i++)
 {
    
    
  if (us[i]==0)
  {
    
    
   us[i]=1;
   no[cr[x]-'A']=i;
   if (check()&&dfs(x+1)) return 1;
   us[i]=0;
  }
 }
 no[cr[x]-'A']=-1;
 return 0;
}
int main()
{
    
    
 memset(no,-1,sizeof(no));
 scanf("%d",&n);
 for (int i=0;i<3;i++)
 {
    
    
  scanf("%s",o[i]);
 }
 for (int i=n-1;i>=0;i--) for (int j=0;j<3;j++)
 {
    
    
  if (vis[o[j][i]-'A']==0)
  {
    
    
   vis[o[j][i]-'A']=1;
   cr[tot++]=o[j][i];
  }
 }
 dfs(0);
 for (int i=0;i<n;i++) printf("%d ",no[i]);
 return 0;
}

致盯着ybtoj系列的OIer:有些ybtoj的题目缺失,是因为之前已经做过重题的题解,就不再补发了

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/113002179