满足等式关系的全排列——dfs+剪枝

数字1 -13 中 选择 12个不同的数 ,组成满足下面加减乘除的等式关系,求解有多少种方案满足如下关系:a1+a2=a3 a4-a5=a6 a7*a8=a9 a10/a11=a12

分析

  1. 此题如果直接爆搜,就直接爆栈对于每个数向下都是121110…,每个数都是13!,13个数就是13*13!。所以需要剪枝!!!
    满足等式关系的全排列——dfs+剪枝_第1张图片
  2. 剪枝的地方就是,在搜第4个位置的数时(当前方案的已确定位置数够判断一个等式,2个不够,5个太多),看看前三个数是否满足等式关系,如果前三个都不满足等式,没必要在当前基础去搜第四个,以及后续的无用搜索;以及第7个位置…
#include

using namespace std;
int visit[20];
int a[20];// 元素的值
int cnt = 0;// 方案数
int n;

void dfs(int i) {
    if (i == 4) // 产生了前面3个元素
    {
        //前三个都不满足等式,没必要在当前基础去搜第四个,以及后续的无用搜索
        if (a[1] + a[2] != a[3])
            return;
    }
    if (i == 7)  // 产生了前面6个元素
    {
        if (a[4] - a[5] != a[6])
            return;
    }
    if (i == 10)  // 产生了9个元素
    {
        if (a[7] * a[8] != a[9]) {
            return;
        }

    }
    if (i == 13)  // 12个元素都产生了,而且 前面3个表达式都成立
    {
        if (a[10] / a[11] == a[12] && a[10] % a[11] == 0) {
            cnt++;
            printf("%d+%d=%d ,%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],
                   a[10], a[11], a[12]);
        }
        return;
    }
    for (int j = 1; j <= n; j++) {
        if (visit[j] == 0) {
            a[i] = j;
            visit[j] = 1;
            dfs(i + 1);
            visit[j] = 0;
        }
    }
}

int main() {
    n = 13;
    dfs(1);
    cout << cnt;
}

你可能感兴趣的:(dfs,深度优先,剪枝,算法)