数学回味系列之20 - 常胜将军

本文介绍了一个经典的取火柴游戏,通过特定的策略确保玩家B能够每次赢得游戏。策略核心是在每轮开始时保证剩余火柴数为5的倍数加1,首次操作尤为关键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题提出:

       规则:A B 两人玩取火柴的游戏,共有 21 根火柴。

                 每人每次最多取 4 根,最少取 1 根。取到最后一根火柴的玩家算输。

                 如何保证某一玩家每次都赢?

        

解题思路:

       常胜将军 是 取火柴游戏 的一个特例。

       如果每次都想让其中一个玩家赢(假设为B),那么B 要保证最后一轮剩余6根,这样不管A怎么取 都会输。

       再往前推,如果上一轮 剩余 5+6 个,那么不管A怎么取,B可以取 5-A 个。

       再进一步,想要占得先机,第一轮就要保证 剩余 5*k + 1 个,第一轮是关键(下手要狠呐)!

       参考代码:

/* linolzhang 2009.12
   Match Game
*/
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main()
{
	printf("请输入火柴数量:");
	int N;
	scanf("%d",&N);

	int A = 0, B = 0;
	while(true)
	{
		if(1 == N)
		{
			printf(" B获胜!\n");
			break;
		}

		printf("你取:");		// A
		A = _getch() - 48;
		if(A<1 || A>4 || A>N)
		{
			printf("非法输入!\n");
			setbuf(stdin, NULL); // 防止输入非法字符导致死循环  
			continue;
		}
		N -= A;
		printf("%d 根  -->  剩余:%d根\n", A,N);

		if(N == 1)		// B
		{
			printf("你获胜!\n");
			break;
		}

		B = (N % 5 + 4) % 5; // 争取剩余 5*k + 1
		if(B == 0)
			B = rand() % 4 + 1; // 被算计了,随便给一个
		N -= B;
		printf(" B取:%d 根  -->  剩余:%d根\n\n", B, N);
	}

	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值