1. 程式人生 > >從暴力列舉到深度優先搜尋

從暴力列舉到深度優先搜尋

題目描述:

\!  \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;
}

注:本題來自《啊哈!演算法》