【C】使用穷举法解决硬币组合与八皇后问题

文章介绍了如何使用穷举法解决两种经典问题:一是寻找特定面值硬币组成目标金额的所有组合,二是放置八皇后确保无冲突的解决方案。通过C语言代码展示了这两种问题的算法思路和实现过程。
摘要由CSDN通过智能技术生成

1.硬币组合问题

在一个陌生的国度,有5种不同的硬币单位:15、23、29、41和67(分)。寻找所有组成18元8分(即808分)的可能组合。
假定对于所有面值的硬币你都有足够的硬币。

思路:

1.定义一个数组coins[],在其中放入5种硬币的面值。

2.使用嵌套循环来穷举所有可能的硬币组合。外层循环控制第一种硬币的数量,内层循环控制第二种硬币的数量,以此类推。

3.在每一次循环中,计算当前组合的总值,并检查是否等于目标值。如果等于目标值,则打印该组合。

#include <stdio.h>

int main() {
    int coins[] = { 15, 23, 29, 41, 67 };
    
    //动态计算硬币数组的元素个数
    //int numCoins = sizeof(coins) / sizeof(coins[0]);     int sum = 808;

    printf("满足条件的硬币组合:\n");

    // 穷举所有可能的硬币组合
    for (int a = 0; a <= sum / coins[0]; a++) {
        for (int b = 0; b <= sum / coins[1]; b++) {
            for (int c = 0; c <= sum / coins[2]; c++) {
                for (int d = 0; d <= sum / coins[3]; d++) {
                    for (int e = 0; e <= sum / coins[4]; e++) {
                        int total = a * coins[0] + b * coins[1] + c * coins[2] + d * coins[3] + e * coins[4];
                        if (total == sum) {
                            printf("%d个15分 + %d个23分 + %d个29分 + %d个41分 + %d个67分\n", a, b, c, d, e);
                        }
                    }
                }
            }
        }
    }

    return 0;
}

2.八皇后问题

八个皇后,分布在八行八列,任意两个皇后不能在同一行(每一行一定有一个皇后),任意两个皇后不能在同一列。
任意两个皇后不能成45度或135度,统计所有皇后能存放的位置和总数。

思路:

1.使用嵌套循环穷举所有的皇后位置组合,将每行各列依次初始化为1(即皇后)。

// 使用穷举法搜索所有皇后的位置

int board[8][8]; // 棋盘,0表示空格,1表示皇后

void findQueenPlace() {

    int count = 0; // 解决方案计数器

    // 遍历所有可能的皇后位置组合
    for (int c0 = 0; c0 < 8; c0++) {
        for (int c1 = 0; c1 < 8; c1++) {
            for (int c2 = 0; c2 < 8; c2++) {
                for (int c3 = 0; c3 < 8; c3++) {
                    for (int c4 = 0; c4 < 8; c4++) {
                        for (int c5 = 0; c5 < 8; c5++) {
                            for (int c6 = 0; c6 < 8; c6++) {
                                for (int c7 = 0; c7 < 8; c7++) {


                                    // 将当前位置设置为皇后位置
                                    for (int i = 0; i < 8; i++) {
                                        for (int j = 0; j < 8; j++) {
                                            board[i][j] = 0;
                                        }
                                    }
                                    board[0][c0] = 1;
                                    board[1][c1] = 1;
                                    board[2][c2] = 1;
                                    board[3][c3] = 1;
                                    board[4][c4] = 1;
                                    board[5][c5] = 1;
                                    board[6][c6] = 1;
                                    board[7][c7] = 1;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}                                                            

2.实现一个判断函数,判断皇后位置是否满足题目所给条件:

1.检查同一列皇后是否冲突
2.检查两条对角线上皇后是否冲突

// 检查当前位置(row, col)是否可以放置皇后
int isRight(int row, int col) {
    // 检查同一列是否冲突
    for (int i = 0; i < row; i++) {
        if (board[i][col] == 1) {
            return 0;
        }
    }
    // 检查右下到左上的对角线是否冲突
    for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 1) {
            return 0;
        }
    }
    // 检查左下到右上的对角线是否冲突
    for (int i = row - 1, j = col + 1; i >= 0 && j < 8; i--, j++) {
        if (board[i][j] == 1) {
            return 0;
        }
    }
    return 1;
}

3.将满足条件的解法打印,并记录解法总数。

// 打印棋盘
void printBoard() {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            printf("%c ", board[i][j] == 1 ? 'Q' : '.');
        }
        printf("\n");
    }
    printf("\n");
}

题解如下:

#include <stdio.h>

int board[8][8]; // 棋盘,0表示空格,1表示皇后

// 打印棋盘
void printBoard() {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            printf("%c ", board[i][j] == 1 ? 'Q' : '.');
        }
        printf("\n");
    }
    printf("\n");
}

// 检查当前位置(row, col)是否可以放置皇后
int isRight(int row, int col) {
    // 检查同一列是否冲突
    for (int i = 0; i < row; i++) {
        if (board[i][col] == 1) {
            return 0;
        }
    }
    // 检查左上到右下的对角线是否冲突
    for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 1) {
            return 0;
        }
    }
    // 检查右上到左下的对角线是否冲突
    for (int i = row - 1, j = col + 1; i >= 0 && j < 8; i--, j++) {
        if (board[i][j] == 1) {
            return 0;
        }
    }
    return 1;
}

// 使用穷举法搜索所有皇后的位置
void findQueenPlace() {

    int count = 0; // 解决方案计数器

    // 遍历所有可能的皇后位置组合
    for (int c0 = 0; c0 < 8; c0++) {
        for (int c1 = 0; c1 < 8; c1++) {
            for (int c2 = 0; c2 < 8; c2++) {
                for (int c3 = 0; c3 < 8; c3++) {
                    for (int c4 = 0; c4 < 8; c4++) {
                        for (int c5 = 0; c5 < 8; c5++) {
                            for (int c6 = 0; c6 < 8; c6++) {
                                for (int c7 = 0; c7 < 8; c7++) {


                                    // 将当前位置设置为皇后位置
                                    for (int i = 0; i < 8; i++) {
                                        for (int j = 0; j < 8; j++) {
                                            board[i][j] = 0;
                                        }
                                    }
                                    board[0][c0] = 1;
                                    board[1][c1] = 1;
                                    board[2][c2] = 1;
                                    board[3][c3] = 1;
                                    board[4][c4] = 1;
                                    board[5][c5] = 1;
                                    board[6][c6] = 1;
                                    board[7][c7] = 1;

                                    // 检查当前棋盘是否满足条件
                                    int isRightBoard = 1;
                                    for (int i = 0; i < 8; i++) {
                                        for (int j = 0; j < 8; j++) {
                                            // 判断皇后位置
                                            if (board[i][j] == 1) {
                                                if (! isRight(i, j)) {
                                                    isRightBoard = 0;
                                                    break;
                                                }
                                            }
                                        }
                                        // 减少循环次数
                                        if (! isRightBoard) {
                                            break;
                                        }
                                    }

                                    // 如果当前棋盘满足八皇后规则,则输出该解决方案
                                    if (isRightBoard) {
                                        count++;
                                        printf("解法 %d :\n", count);
                                        printBoard();
                                    }


                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // 输出解决方案的总数
    printf("综上,共有 %d 种解决方法 \n", count);
}

int main() {

    findQueenPlace();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值