说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

七根火柴题

编辑:说三道四文库 发布时间:2018-07-20 10:55
HTML文档下载 WORD文档下载 PDF文档下载
题:七根火柴,甲乙两人每次抽取一到两根,最后抽取的人获胜。如果甲先抽,获胜的所有方案列印出来。
今天的一道考试题,几年没摸数据结构了,没做出来,好是沮丧!
甲先抽1, 接下来,如果乙抽1,甲就抽2, 乙抽2,甲就抽1, .....


不管几根火柴都是先抽的胜
最好请写出程序算法
提示思路:
从后往前算,最后剩下1/2根被甲抽到,依次往前加,乙抽、甲抽、乙抽、甲抽...,每次1/2根,如果加完后共是7根且为甲所加,则输出。
算法与货郎担类似。
1fei(白天):
真的么?如果只有3根火柴呢?:-)
取火柴问题就是著名的Nim问题,当然你这个问题比较简单,不用Nim解决也可以

如果想了解,察看:
http://www.csdn.net/expert/topic/424/424009.shtm
Next(0)不存在,|0|=0
Next(1)={0},next(1)={0},|1|=1
Next(2)={0,1};next(2)={1,0} |2|=2
Next(3)={1,2};next(3)={1,2} |3|=0
Next(4)={2,3};next(4)={0,2} |4|=1
Next(5)={4,3};next(5)={1,0} |5|=2
Next(6)={5,4};next(6)={1,2} |6|=0
Next(7)={6,5};next(7)={0,2} |7|=1
因此7根火柴必胜。
可以证明,
|3k|=0
|3k+1|=1
|3k+2|=2





如果要写出方案通过Next和next的组合就可以了,就是找0值.
A:7->6-->5->3-->2-->0
             -->1-->0 
      -->4->3-->2-->0
             -->1-->0
  



只要使剩下的是三的倍数就行了
对于N根火柴情况
N mod 3 =0 则先抽的必输
否则先抽必胜!
先下比赢。
倒推吧!
#include <iostream.h>

const int MAX_MATCH_COUNT = 100;
bool FirstWin[MAX_MATCH_COUNT + 1];  // FirstWin[i]=true 表示有i根火柴的时候先取者必胜,
                                     // FirstWin[i]=false表示有i根火柴的时候先取者必败

int match_count, max_fetch;     // match_count 火柴数目, max_fetch 每次最多可取的火柴的数目

int strategy[MAX_MATCH_COUNT];  // 用来记录取火柴的策略

int min(int a, int b) {
    return (a < b ? a : b);
}

// 计算在哪些情况下先取者必胜或必败
void CalFirstWin() 
{
    FirstWin[0] = false;
    for (int i = 1; i <= match_count; i++) {
        FirstWin[i] = false;
        for (int j = 1; j <= min(max_fetch, i); j++) {
            if (FirstWin[i - j] == false) {
                FirstWin[i] = true;
                break;
            }
        }        
    }
}

// 打印必胜策略
void PrintStrategy(int n, bool A_Fetch, int step)
{
    if (n == 0) {
        for (int i = 0; i < step; i++) {
            cout << strategy[i] << " ";
        }
        cout << endl;
        return;
    }
    
    if (A_Fetch) { // 轮到A取
        for (int i = 1; i <= min(max_fetch, n); i++) {
            if (FirstWin[n - i] == false) {
                strategy[step] = i;
                PrintStrategy(n - i, false, step + 1);
                return;
            }
        }
    } else {  // 轮到B取
        for (int i = 1; i <= min(max_fetch, n); i++) {
            // 对B的每一种取法都给出必胜策略
            strategy[step] = i;
            PrintStrategy(n - i, true, step + 1);
        }
    }    
}

void main()
{         
    match_count = 7; 
    max_fetch   = 2;

    CalFirstWin();
    if (FirstWin[match_count] == false) {
        cout << "A can not win!" << endl;
    } else {
        PrintStrategy(match_count, true, 0);
    }
}
感谢starfish,同时也敬佩无比!
我拿到这种题怎么也找不到思路,能否指教我,如何构思这类题?感激不尽!
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘