[USACO][Section 1.3][搜索] Prime Cryptarithm

题目大意:

题目给出一个由“*”构成的乘法式子。已知一个范围为[0,9]的整数集合,用集合中的数字替换“*”可能使式子成立,要求编程求出使式子成立的方案的数量。

思路:

用深搜遍历所有可能方案即可,具体思路见代码。

代码:

/*
ID: lujunda1
LANG: C++
PROG: crypt1
*/
#include
#include
#include
#include
#include
using namespace std;
//num[]用于存储两个乘数,例如123*45,那么num[]={1,2,3,4,5}。 
int num[5];
//mark[]用于判断某数字是否属于所给集合。 
bool mark[10];
//输入 
void input()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<10;i++)
        mark[i]=false;
    for(int i=0,temp;i<n;i++)
    {
        scanf("%d",&temp);
        mark[temp]=true;
    }
}
//判断整数n的各位数字是否都属于集合 
int check_num(int n)
{
    //length用于记录整数n的长度。 
    int length=0;
    for(;n;n/=10,length++)
        //若某位数字不属于集合,则返回-1。 
        if(!mark[n%10])
            return -1;
    //若整数n的各位数字都属于集合,则返回其长度。
    //返回长度是因为题目所给乘法式子对不同位置的整数有格式(长度)限制,要判断整数n是否符合格式。 
    return length;
}
//判断当前num[]所表示的乘数组合是否符合乘法式子与格式的要求。 
bool check()
{
    //a是被乘数,b是乘数,d是乘数的个位,c是乘数的十位。 
    int a=num[0]*100+num[1]*10+num[2],b=num[3]*10+num[4],c=num[4],d=num[3];
    //a*c和a*d分别是乘法式子第4行和第3行上的整数。它们的长度为3。 
    //a*b是结果,长度应该为4。 
    if(check_num(a*c)==3&&check_num(a*d)==3&&check_num(a*b)==4)
        return true;
    return false;
}
//利用深搜,遍历所有可能的乘数组合。
//order表示num[]中的第order位,从0开始。 
int dfs(int order)
{
    if(order==5)
        return check()?1:0;
    int sum=0;
    for(int i=0;i<10;i++)
        if(mark[i])
        {
            //不能有前导0 
            if((order==0||order==3)&&i==0)
                continue;
            num[order]=i;
            sum+=dfs(order+1);
        }
    return sum;
}
int main()
{
    freopen("crypt1.in","r",stdin);
    freopen("crypt1.out","w",stdout);
    input();
    printf("%d\n",dfs(0));
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注