巴什博弈hdu 1846
1、 本遊戲是乙個二人遊戲;
2、 有一堆石子一共有n個;
3、 兩人輪流進行;
4、 每走一步可以取走1…m個石子;
5、 最先取光石子的一方為勝;
這個應該比較好推:
如果 n % (m+1)==0 後手勝利 否則 先手勝利
#include#include#includeusing namespace std;
int main()
return 0;
}
斐波拉契博弈hdu 2516
有一堆個數為n(n>=2)的石子,遊戲雙方輪流取石子,規則如下:
1、先手不能在第一次把所有的石子取完,至少取1顆;
2、之後每次可以取的石子數至少為1,至多為對手剛取的石子數的2倍;
3、約定取走最後乙個石子的人為贏家;
f[1]=1,f[2]=2的斐波那契數列
如果n為斐波拉契數列的一項,那麼先手必敗,否則先手必勝。
有篇解釋的很清楚的部落格:
#include#include#includeusing namespace std;
typedef long long ll;
ll f[50];
int main()
} if(flag) puts("second win");
else puts("first win");
} return 0;
}
hdu 1564 稍加一些思維的博弈乙個n*n矩陣,一開始從左下角(任何乙個角落)開始走 不能走走過的格仔 問先手勝利還是後手勝利
我們畫出n*n的矩陣 並且講它進行分解
如果n為偶數 我們可以把它分解成很多個1*2的方塊 先手每次走到包含當前格仔的另外乙個方塊上就行 此時先手必勝
如果n為奇數 我們把起始點拿出來 剩下的格仔也能分成很多 1*2的方塊 此時先手每次走入乙個新的方塊 而後手走到這個方塊的另乙個格仔就行 此時後手必勝
#include#include#includeusing namespace std;
int main()else
} return 0;
}
hdu 1525有兩個玩家,stan 和 ollie, 在玩遊戲。初始有兩個自然數。stan是先手,每次把大的數字減去小的數字的任意倍數,但是不能使數字變成負數。然後ollie進行同樣的操作,直到有乙個玩家使乙個數字變為零。
例如,初始時數字為(25,7):
25 7
11 7
4 74 3
1 31 0
這樣stan贏
要掌握一種思維 如果我走一步可以讓下乙個人達到必敗態 那我肯定是能贏的 這是顯然易見的
假設a>b 當a%b==0 顯然是當前操作的人勝利
當a>=2*b 也是當前操作的人勝利 為什麼呢 我們可以看 a%b,b的狀態是必敗態還是必勝態 如果是必敗態 那麼我就走到這個狀態 讓下乙個操作的人輸 否則我就走到 a%b+b,b這個狀態(是必敗的 因為它只能走到乙個必勝態a%b,b)
當a>b&&a<2*b時 進行一次簡單的操作(a=a%b,b=b) 然後更換一下當前操作的人就行了
#include#include#includeusing namespace std;
int main()
return 0;
}
nim博弈 hdu - 1850nim博弈是比較經典的博弈:桌子上有m堆撲克牌;每堆牌的數量分別為ai (i=1…m);兩人輪流進行;每走一步可以任意選擇一堆並取走其中的任意張牌;桌子上的撲克全部取光,則遊戲結束;最後一次取牌的人為勝者。
先手必勝當且僅當 a[1]^a[2]^a[3]....^a[m] != 0
我們可以這樣推導
假設 a[1]^a[2]^a[3]....^a[m] = x, 那麼肯定存在乙個牌堆 它的牌數目為a[i] 並且a[i]^x因此我們可以在 i 牌堆裡面取適當數目的牌 使得 a[i]->a[i]^x
到另外乙個人取牌的時候 a[1]^a[2]^a[3]....^a[m] = 0, 根據異或的性質 無論他怎麼取 取完以後 a[1]^a[2]^a[3]....^a[m] != 0
由數學歸納法可知: a[1]^a[2]^a[3]....^a[m] != 0 為必勝局面,一定存在一種行動讓對手面臨 「各堆牌異或起來等於0」 。 a[1]^a[2]^a[3]....^a[m] = 0 為必敗局面,無論如何行動,都會讓對手面臨乙個「各堆石子異或起來不等於0」 的必勝局面。
在來看這題 第一步能走的方案數 那肯定是 現求出 x 在遍歷a陣列 如果 a[i]>a[i]^x 則方案數+1
#includeusing namespace std;
int a[102];
int main()+1)/2" class="mathcode" src=""/>
#include#include#includeusing namespace std;
int main()
return 0;
}
映象原理 hdu - 3951映象原理:博弈論常用小技巧,當對方先操作時,我們可以模仿對方的操作來進行映象的操作以達到必勝的目的
首先看乙個簡單的題 乙個長度為n的序列(首尾不相連) a,b兩人輪流進行操作 每次可以取連續的k(k<=n) 個數 最後取完的人勝利 (ps:如果第3個數被取了 那麼2和4不能同時取)
顯然 如果 k==1 我們可以通過n的奇偶性判斷輸贏 如果n&1先手勝利 否則後手勝利
接下來就是映象原理的應用了:
k>=2的時候 先手可以從序列 居中的位置 取1個或2個連續的數 使得序列的左右兩端長度相同 進行完這個操作後 無論後手怎麼取 先手在對應的映象中取就行了 這樣先手是必勝的
hdu - 3951 這題把序列首尾相連變成了環形 當先手取完一次以後就變成序列了 然後再按上述方法 後手可以必勝 另外注意判斷一下特殊情況就行
#includeusing namespace std;
int main()
if(k==1&&n%2)
puts("second");
} return 0;
}
階梯博弈變形 hdu - 3389普通的階梯博弈: 有n階從左往右遞增的樓梯 每一階上有一定數量的石子(可以為0) 0是最低階 兩個人輪流操作 每次操作可以選乙個階梯 取》0顆石子 往下放(放到左邊的下一階上) 最先不能操作的人輸
看成奇數號階梯的nim博弈:我們這樣思考 當我把石子從奇數號階梯拿到偶數號階梯時 可以看做nim博弈的取石子操作 如果後手把偶數號階梯的石子放到了奇數號階梯 那先手只要把這些石子在放回偶數號階梯就行 仍然可以保證奇數號階梯的nim博弈
再來看這道題 題意可以轉化一下: b#include#includeusing namespace std;
int main()
printf("case %d: ",++ca);
if(xo) puts("alice");
else puts("bob");
} return 0;
}
簡單sg函式 hdu - 3032在nim博弈的基礎上增加了乙個分石子的操作 但是因為石子數目較大 無法直接打sg表 乙個常用的方法就是打一小部分的sg表 然後觀察規律即可 於是我打出了石子數小於等於100的sg表 經過觀察得知
x%4==1||x%4==2 return x
x%4==3 return x+1
x%4==0 return x-1
#includeusing namespace std;
int vis[105],sg[105];
void init()
} for(int i = 0; i <= 100; i++) printf("sg[%d]=%d\n",i,sg[i]);
}int getsg(int x)
int main()
return 0;
}
博弈論題目整理
hdu 1079 暴力pn打錶能過或不太好找的規律 打表比較麻煩 hdu 1525 分析規律 暴力pn打表無法獲得直觀規律,pn打表提交炸時空 hdu 1564 超簡單的規律 無法pn 超水 hdu 1846 巴什模板 超水 hdu 1847 pn找規律 也可直接打表提交 水 hdu 2516 斐波...
簡單博弈論題目總結
bashgame i 有一堆石子共有n個。a b兩個人輪流拿,a先拿。每次最少拿1顆,最多拿k顆,拿到最後1顆石子的人獲勝。假設a b都非常聰明,拿石子的過程中不會出現失誤。給出n和k,問最後誰能贏得比賽。例如n 3,k 2。無論a如何拿,b都可以拿到最後1顆石子。include include u...
博弈論 入門,持續更新
本篇只對尼姆博弈和巴什博弈進行介紹 其餘博弈遇到了再加進去 定義 博弈論,又稱為對策論 game theory 賽局理論等,既是現代數學的乙個新分 支,也是運籌學的乙個重要學科。博弈論 是二人在平等的對局中各自利用對方的策略變換自己的 對抗策略,達到取勝的目的。巴什博弈 只有一堆n個物品,兩個人輪流...