从暴力枚举到深度优先搜索

题目描述:

\!  \square \square \square+\square \square \square=\square \square \square

  将数字1~9分别填入9个\square中,每个数字只能使用一次使得等式成立。

  例如173+286=459 就是一个合理的组合,请问一共有多少组合呢?

  注意:173+286=459 与 286+173=459 是同一种组合!

暴力枚举:

  枚举每一位上所有的可能,判断等式是否成立就好了:

#include <stdio.h>
int main(){
    int a,b,c,d,e,f,g,h,i,total=0;
    for(a=1;a<=9;a++)
    for(b=1;b<=9;b++)
    for(c=1;c<=9;c++)
    for(d=1;d<=9;d++)
    for(e=1;e<=9;e++)
    for(f=1;f<=9;f++)
    for(g=1;g<=9;g++)
    for(h=1;h<=9;h++)
    for(i=1;i<=9;i++)
    {//接下来要判断每一位上的数互不相等
        if(a!=b && a!=c && a!=d && a!=e && a!=f && a!=g && a!=h && a!=i
                && b!=c && b!=d && b!=e && b!=f && b!=g && b!=h && b!=i
                        && c!=d && c!=e && c!=f && c!=g && c!=h && c!=i
                                && d!=e && d!=f && d!=g && d!=h && d!=i
                                        && e!=f && e!=g && e!=h && e!=i
                                                && f!=g && f!=h && f!=i
                                                        && g!=h && g!=i
                                                                && h!=i
                            && a*100+b*10+c+d*100+e*10+f==g*100+h*10+i)
        {
            total++;
            printf("%d%d%d+%d%d%d=%d%d%d\n",a,b,c,d,e,f,g,h,i);
        }
    }
    printf("total=%d",total/2);
    getchar();getchar();
    return 0;
}

  判断9个数互不相等的部分,可使用一个book标记数组使代码更简洁:

#include <stdio.h>
int main(){
    int a[10],i,total=0,book[10],sum;
    for(a[1]=1;a[1]<=9;a[1]++)
        for(a[2]=1;a[2]<=9;a[2]++)
            for(a[3]=1;a[3]<=9;a[3]++)
                for(a[4]=1;a[4]<=9;a[4]++)
                    for(a[5]=1;a[5]<=9;a[5]++)
                        for(a[6]=1;a[6]<=9;a[6]++)
                            for(a[7]=1;a[7]<=9;a[7]++)
                                for(a[8]=1;a[8]<=9;a[8]++)
                                    for(a[9]=1;a[9]<=9;a[9]++)
                                    {
                                        //初始化book数组
                                        for (i=1; i<=9; i++)    book[i]=0;
                                        for(i=1;i<=9;i++)   book[a[i]]=1;
                                        //统计共出现了多少个不同的数
                                        sum=0;
                                        for (i=1; i<=9; i++)    sum+=book[i];
                                        //如果刚好出现了9个不同的数,并且满足等式,则输出
                                        if (sum == 9 && a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9])
                                        {
                                            total++;
                                            printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
                                        }
                                    }
    printf("total=%d",total/2);
    getchar();getchar();
    return 0;
}

深度优先搜索: 

  依次将1~9分别填入9个\square中,判断等式是否成立,重点在于如何不重复填入,见注释:

#include <stdio.h>
int a[10],book[10],total=0;
//a数组为方框,即在a[1]-a[9]中分别填入9个数,使得等式成立,book为标记数组
void dfs(int step)//step表示当前需要填的是哪一个框
{
    if(step == 10)//当9个框都填满时,判断等式是否成立
    {
        if((a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]) == (a[7]*100+a[8]*10+a[9]))
        {
            total++;
            printf("%d%d%d + %d%d%d = %d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
        }
        
        return;
    }
    for (int i=1; i<=9; i++)
    {
        //如果i没有被填进框
        if (book[i] == 0)
        {
            a[step] = i;//把i填入当前的框
            book[i] = 1;//标记i已经被填入
            dfs(step+1);//去填下一个框
            book[i] = 0;//每填完9个框,标记数组重新清零
        }
    }
    return;
}
int main(){
    dfs(1);
    printf("total=%d",total/2);//每个式子都算了两次,所以除以2
    getchar();getchar();
    return 0;
}

注:本题来自《啊哈!算法》 

猜你喜欢

转载自blog.csdn.net/kisick/article/details/84449788