2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS

基爷与加法等式

Time Limit: 20 Sec  Memory Limit: 256 MB

题目连接

http://acm.uestc.edu.cn/#/contest/show/61

Description

字母加法等式

一天,上小学的妹妹跑过来问基爷一道字母加法等式,基爷不假思索的便给出了一组可行解。

聪明的你发现,一个字母等式可能有多种不同解,于是你想编个程序计算一下

Input

输入包含多组数据。

每组数据第一行一个整数n,表示有n个字符串 3 ≤ n ≤ 10

接下来n行,每行有1个最多只含10个大写字母的字符串,前 n - 1 行的字符串表示加数,第 n 行的字符串表示和

每个样例最多只有10个互不相同的大写字母,每个字母表示 0 - 9 中的一个数,相同字母表示相同的数,不同字母表示不同的数输入包含多组数据。

每组数据第一行一个整数n,表示有n个字符串 3 ≤ n ≤ 10

接下来n行,每行有1个最多只含10个大写字母的字符串,前 n - 1 行的字符串表示加数,第 n 行的字符串表示和

每个样例最多只有10个互不相同的大写字母,每个字母表示 0 - 9 中的一个数,相同字母表示相同的数,不同字母表示不同的数

Output

对于每组数据输出一个整数,表示不同的可行解的数量。

对于两个可行解,只要有一个字母表示不同的数字,我们就认为这两个可行解不同

 

Sample Input

4
TAI
SHEN
LA
ACER
3
SEND
MORE
MONEY

Sample Output

76
1

HINT

 

  1. 如果各个字符串长度不等,右对齐后再运算
  2. 每个字符串最左边的字母表示的数字不能为0
  3. 不保证最后一个字符串的长度大于等于前面的表示加数的字符串长度

题意

 

题解:

直接爆搜就好了,唯一要注意的就是从低位开始搜

代码:

 

//qscqesze

#include <cstdio>

#include <cmath>

#include <cstring>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <set>

#include <vector>

#include <sstream>

#include <queue>

#include <typeinfo>

#include <fstream>

#include <map>

#include <stack>

typedef long long ll;

using namespace std;

//freopen("D.in","r",stdin);

//freopen("D.out","w",stdout);

#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)

#define maxn 200001

#define mod 10007

#define eps 1e-9

int Num;

char CH[20];

//const int inf=0x7fffffff;   //нчоч╢С

const int inf=0x3f3f3f3f;

/*



inline void P(int x)

{

    Num=0;if(!x){putchar('0');puts("");return;}

    while(x>0)CH[++Num]=x%10,x/=10;

    while(Num)putchar(CH[Num--]+48);

    puts("");

}

*/

inline ll read()

{

    int x=0,f=1;char ch=getchar();

    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}

    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}

    return x*f;

}

inline void P(int x)

{

    Num=0;if(!x){putchar('0');puts("");return;}

    while(x>0)CH[++Num]=x%10,x/=10;

    while(Num)putchar(CH[Num--]+48);

    puts("");

}

//**************************************************************************************



int mp[30];

int H[30];

string s[11];

int n,tmp;

char k[100];

int vis[12],ans=0,ma;

int tp[30];

int ans1[30];

int ans2[30];

int check()

{

    ans1[ma]=0;

    for(int i=ma-1;i>=0;i--)

    {

        ans1[i]=0;

        ans2[i]=0;

        for(int j=0;j<n-1;j++)

        {

            if(H[s[j][i]-'A']==-1)

                return 0;

            ans1[i]+=H[s[j][i]-'A'];

        }

        ans1[i]+=(ans1[i+1]/10);

        if(H[s[n-1][i]-'A']==-1)

            return 0;

        ans2[i]+=H[s[n-1][i]-'A'];

        if((ans1[i]%10)!=ans2[i])

            return 1;

    }

    if(ans1[0]>9)

        return 1;

    return 0;

}

void dfs(int x)

{

    if(x==tmp)

    {

        ans++;

        return;

    }

    for(int i=9;i>=0;i--)

    {

        if(i==0&&tp[k[x]-'A'])

            continue;

        if(vis[i])

            continue;

        vis[i]=1;

        H[k[x]-'A']=i;

        if(!check())

            dfs(x+1);

        vis[i]=0;

        H[k[x]-'A']=-1;

    }

}



int main()

{

    while(scanf("%d",&n)!=EOF)

    {

        for(int i=0;i<30;i++)

            mp[i]=tp[i]=H[i]=0;

        ma=0;

        for(int i=0;i<n;i++)

            cin>>s[i],ma=max(ma,(int)s[i].size());

        for(int i=0;i<n;i++)

            tp[s[i][0]-'A']=1;

        for(int i=0;i<n;i++)

        {

            int len=s[i].size();

            for(int j=0;j<ma-len;j++)

            {

                s[i]='['+s[i];

            }

        }

        tmp=0;

        ans=0;

        for(int i=ma-1;i>=0;i--)

        {

            for(int j=0;j<n;j++)

            {

                if(mp[s[j][i]-'A'])

                    continue;

                if(s[j][i]=='[')

                    continue;

                k[tmp++]=s[j][i];

                mp[s[j][i]-'A']=1;

            }

        }

        for(int i=0;i<tmp;i++)

            H[k[i]-'A']=-1;



        H['['-'A']=0;

        dfs(0);

        printf("%d\n",ans);

    }

}

 

你可能感兴趣的:(DFS)