hdu1850-Being a Good Boy in Spring Festival (博弈論 Nim博弈)

Being a Good Boy in Spring Festival

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3972    Accepted Submission(s): 2345


Problem Description
一年在外 父母時刻牽掛
春節回家 你能做幾天好孩子嗎
寒假裏嘗試做做下面的事情吧

陪媽媽逛一次菜場
悄悄給爸爸買個小禮物
主動地 強烈地 要求洗一次碗
某一天早起 給爸媽用心地做回早餐

如果願意 你還可以和爸媽說
咱們玩個小遊戲吧 ACM課上學的呢~

下面是一個二人小遊戲:桌子上有M堆撲克牌;每堆牌的數量分別爲Ni(i=1…M);兩人輪流進行;每走一步可以任意選擇一堆並取走其中的任意張牌;桌子上的撲克全部取光,則遊戲結束;最後一次取牌的人爲勝者。
現在我們不想研究到底先手爲勝還是爲負,我只想問大家:
——“先手的人如果想贏,第一步有幾種選擇呢?”
 

Input
輸入數據包含多個測試用例,每個測試用例佔2行,首先一行包含一個整數M(1<M<=100),表示撲克牌的堆數,緊接着一行包含M個整數Ni(1<=Ni<=1000000,i=1…M),分別表示M堆撲克的數量。M爲0則表示輸入數據的結束。
 

Output
如果先手的人能贏,請輸出他第一步可行的方案數,否則請輸出0,每個實例的輸出佔一行。
 

Sample Input
3 5 7 9 0
 

Sample Output
1
 
             思路:如果所有堆的撲克牌數異或值等於0,那麼先手爲奇異局勢(先手必輸 在選手不犯錯情況下)。由此某一堆撲克牌的異或值,等於剩餘全部堆的異或值,那麼此局是奇異局勢,因爲必勝局勢必存在可以轉換成奇異局勢,那麼某一堆的值 大於剩餘堆撲克牌(也就是說這堆撲克牌可以取走某些數使其值等於剩餘堆的異或數),那麼這爲一種必勝選擇,遍歷所有堆得出結果。
 
 
 
/***************************************************
*
*	acm: hdu-1850
*
*	title: Being a Good Boy in Spring Festival
*
*	time: 2014.5.4
*
***************************************************/

//此題考察博弈論,Nim博弈

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    int j;
    int k;
    int M;   //M堆撲克牌

    while (~scanf("%d", &M) && M != 0)
    {
        int N[101] = {0};   
        int sum = 0;   //除當前堆,剩餘堆得異或值
        int num = 0;   //必勝結果的選擇數

        for (i=1; i<=M; i++)
        {
            scanf("%d", &N[i]);  //每一堆撲克牌的數量
        }

        for (i=1; i<=M; i++)
        {
            k = i;
            sum = 0;

            for (j=1; j < k; j++)  //當前堆之前的所有堆
            {
                sum ^= N[j];
            }

            for (j = i + 1; j <= M; j++)//當前堆之後的所有堆
            {
                sum ^= N[j];
            }

            if (N[k] > sum) //如果當前堆值大於 剩餘堆的異或值 則結果勝利
            {
                num++;
            }
        }

        printf("%d\n", num);
    }

    return 0;
}
 

還有種思路,算是上面程序的優化把
/***************************************************
*
*	acm: hdu-1850
*
*	title: Being a Good Boy in Spring Festival
*
*	time: 2014.5.4
*
***************************************************/

/*
    理論:a+b=s,有 b=s+a  (a表示某分堆,b表示其餘分堆的異或值,s爲總異或值)
即總異或和s 對任意一個數a取異或 可以的得到其他所有數的異或值b。

	思路:if (b = s + a < a) 成立
 a可以減到b使其異或爲0  則有必勝策略

e.g
s = 5 + 7 + 9 = 0101 + 0111 + 1001 = 1011B = 11D
b = s + a = 11 + 5 = 1011 + 0101 = 1110B = 14D
b = 7 + 9 = 0111 + 1001 = 1110B = 14D

because : a < b 
so:  從5取任何數都無法轉爲必敗點

if (s != 0) 遍歷剩餘所以堆, 必存在能轉爲必敗點的某堆

*/

#include<stdio.h>

#define MAXSIZE 100

int main()
{
    int M;
	int N[MAXSIZE];

    while (~scanf("%d", &M) && M != 0)
    {
        int i;
        int sum = 0;
		int num = 0;

        for (i = 0; i < M; i++)
        {
            scanf("%d", &N[i]);
            sum ^= N[i];
        }

		for (i = 0; i < M; i++)
		{
			if (N[i] > (N[i]^sum))
			{
				num++;
			}
		}

		printf("%d\n", num);

    }

    return 0;
}


 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章