三个鸡蛋(玻璃球、围棋子)确定楼层问题公式推导

文章原先发表在:http://blog.163.com/cyhuoyan@126/blog/static/1623497552013368914262/

1)题目是这样的:一个100层的大厦,你手中有两个相同的玻璃球。从这个大厦的某一层扔下围棋子就会碎,用你手中的这两个玻璃围棋子,找出一个最优的策略,来得知那个临界层面。
    
这里的最优策略指的是在这种策略下无论哪个临界层面在第几层,测试的次数最少。我一开始就是把题意理解错了,给了一个非最优解,后来看了CU那的讨论后才明白了是用动态规划来做,并可以把题目扩展为n层大厦用k个玻璃球来测试。
    
F(n,k)为用k个玻璃球来测试n层大厦的临界层的最少次数,状态转移方程如下:
    F(n,k)=min{max{F(r,k-1), F(n-r,k)}+1, 1<=r<=n}
    
边界条件:F(n,1)=n-1, F(1,k)=F(0,k)=0
    
状态转移方程可以这样来考虑,假设在n层楼中的第r层抛一次(对应方程中的"+1"),会有两种情况发生:
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的双人对弈围棋程序,使用C语言编写,基于CodeBlocks开发环境。 ``` #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define SIZE 9 typedef enum { EMPTY, BLACK, WHITE } stone; void print_board(stone board[SIZE][SIZE]) { printf(" "); for (int i = 0; i < SIZE; i++) printf("%c ", 'A' + i); printf("\n"); for (int i = 0; i < SIZE; i++) { printf("%d ", i + 1); for (int j = 0; j < SIZE; j++) { if (board[i][j] == EMPTY) printf(". "); else if (board[i][j] == BLACK) printf("X "); else printf("O "); } printf("%d\n", i + 1); } printf(" "); for (int i = 0; i < SIZE; i++) printf("%c ", 'A' + i); printf("\n"); } bool is_valid_move(stone board[SIZE][SIZE], int row, int col, stone player) { if (row < 0 || row >= SIZE || col < 0 || col >= SIZE) return false; if (board[row][col] != EMPTY) return false; stone opponent = (player == BLACK) ? WHITE : BLACK; if ((row > 0 && board[row - 1][col] == opponent) || (row < SIZE - 1 && board[row + 1][col] == opponent) || (col > 0 && board[row][col - 1] == opponent) || (col < SIZE - 1 && board[row][col + 1] == opponent)) return true; return false; } void place_stone(stone board[SIZE][SIZE], int row, int col, stone player) { board[row][col] = player; } bool is_captured(stone board[SIZE][SIZE], int row, int col) { if (board[row][col] == EMPTY) return false; stone opponent = (board[row][col] == BLACK) ? WHITE : BLACK; if ((row > 0 && board[row - 1][col] == opponent && !is_liberty(board, row - 1, col)) || (row < SIZE - 1 && board[row + 1][col] == opponent && !is_liberty(board, row + 1, col)) || (col > 0 && board[row][col - 1] == opponent && !is_liberty(board, row, col - 1)) || (col < SIZE - 1 && board[row][col + 1] == opponent && !is_liberty(board, row, col + 1))) return true; return false; } bool is_liberty(stone board[SIZE][SIZE], int row, int col) { if (board[row][col] == EMPTY) return true; if (row > 0 && board[row - 1][col] == EMPTY) return true; if (row < SIZE - 1 && board[row + 1][col] == EMPTY) return true; if (col > 0 && board[row][col - 1] == EMPTY) return true; if (col < SIZE - 1 && board[row][col + 1] == EMPTY) return true; return false; } void remove_stone(stone board[SIZE][SIZE], int row, int col) { board[row][col] = EMPTY; } bool is_legal_move(stone board[SIZE][SIZE], int row, int col, stone player) { if (!is_valid_move(board, row, col, player)) return false; place_stone(board, row, col, player); bool legal = !is_captured(board, row, col); remove_stone(board, row, col); return legal; } int count_liberties(stone board[SIZE][SIZE], int row, int col) { int liberties = 0; if (row > 0 && board[row - 1][col] == EMPTY) liberties++; if (row < SIZE - 1 && board[row + 1][col] == EMPTY) liberties++; if (col > 0 && board[row][col - 1] == EMPTY) liberties++; if (col < SIZE - 1 && board[row][col + 1] == EMPTY) liberties++; return liberties; } bool is_eye(stone board[SIZE][SIZE], int row, int col, stone player) { if (board[row][col] != EMPTY) return false; if (count_liberties(board, row, col) != 2) return false; stone opponent = (player == BLACK) ? WHITE : BLACK; int border_count = 0; if (row == 0 || row == SIZE - 1) border_count++; if (col == 0 || col == SIZE - 1) border_count++; if (border_count == 1) return false; if ((row > 0 && board[row - 1][col] == player) || (row < SIZE - 1 && board[row + 1][col] == player) || (col > 0 && board[row][col - 1] == player) || (col < SIZE - 1 && board[row][col + 1] == player)) return false; int opponent_count = 0; if (row > 0 && board[row - 1][col] == opponent) opponent_count++; if (row < SIZE - 1 && board[row + 1][col] == opponent) opponent_count++; if (col > 0 && board[row][col - 1] == opponent) opponent_count++; if (col < SIZE - 1 && board[row][col + 1] == opponent) opponent_count++; if (opponent_count > 1) return false; return true; } bool is_valid_eye(stone board[SIZE][SIZE], int row, int col, stone player) { if (!is_eye(board, row, col, player)) return false; stone opponent = (player == BLACK) ? WHITE : BLACK; int friendly_stones = 0; int enemy_stones = 0; if (row > 0) { if (board[row - 1][col] == player) friendly_stones++; else if (board[row - 1][col] == opponent) enemy_stones++; } if (row < SIZE - 1) { if (board[row + 1][col] == player) friendly_stones++; else if (board[row + 1][col] == opponent) enemy_stones++; } if (col > 0) { if (board[row][col - 1] == player) friendly_stones++; else if (board[row][col - 1] == opponent) enemy_stones++; } if (col < SIZE - 1) { if (board[row][col + 1] == player) friendly_stones++; else if (board[row][col + 1] == opponent) enemy_stones++; } if (friendly_stones == 4 || enemy_stones > 0) return false; return true; } bool is_valid_placement(stone board[SIZE][SIZE], int row, int col, stone player) { if (is_valid_move(board, row, col, player)) { if (is_legal_move(board, row, col, player)) { if (!is_valid_eye(board, row, col, player)) { return true; } } } return false; } stone get_player(int move_number) { return (move_number % 2 == 0) ? BLACK : WHITE; } int main() { stone board[SIZE][SIZE] = { EMPTY }; int move_number = 0; while (true) { print_board(board); stone player = get_player(move_number); printf("%c's turn (e.g. B4): ", (player == BLACK) ? 'X' : 'O'); char input[3]; scanf("%s", input); if (input[0] == 'q' || input[0] == 'Q') break; int row = input[1] - '1'; int col = input[0] - 'A'; if (is_valid_placement(board, row, col, player)) { place_stone(board, row, col, player); move_number++; } else { printf("Invalid move.\n"); } } return 0; } ``` 这个程序实现了基本的落子、吃子和判断胜负的功能,可以通过控制台输入坐标来进行游戏。但是这个程序还有很多不足之处,比如没有对禁手规则进行处理,也没有判断胜负的算法。如果需要更加完善的围棋程序,需要进一步优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值