日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SG函数详解

發(fā)布時(shí)間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SG函数详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在之前的博客中我主要介紹了幾種常見的博弈論,那些都比較固定,當(dāng)我們遇到一些新型的博弈問題時(shí),未必可以用之前的模型去解決他,現(xiàn)在我就來介紹一種工具來解決規(guī)則比較奇怪的博弈游戲。

先來說一下可以用SG函數(shù)解決的問題所需要滿足的條件:

(1)游戲人數(shù)為兩人

(2)兩人交替進(jìn)行某種游戲規(guī)定的操作,每次操作,選手都可以在當(dāng)前合法的操作中選取一種

(3)對于游戲的任意一種可能的局面,合法的操作集合只取決于這個(gè)局面的本身,而與操作者無關(guān)

就拿巴什博弈舉例,每個(gè)操作者每次都可以拿走1~m塊石頭,每次拿走石頭的個(gè)數(shù)取決于當(dāng)前還剩多少塊石頭,而與之前的操作無關(guān),這就是一個(gè)可以利用SG函數(shù)來解決的問題。

下面來對P-position(必?cái)↑c(diǎn))和N-position(必勝點(diǎn))來作下解釋:

處在必勝點(diǎn)的選手如果不出現(xiàn)決策上的失誤,則選手是必勝的,同理,處在必?cái)↑c(diǎn)的選手是必?cái)〉摹?/p>

依舊拿巴什博弈舉例,假如一開始給定m+2塊石頭,每次可以取1~m塊石頭,則先手必勝,所以m+2也就是一個(gè)必勝點(diǎn),若一開始給定m+1塊石頭,則無論先手第一次取幾塊石頭,后手都可以一次性取完剩余的石頭,所以m+1是一個(gè)必?cái)↑c(diǎn)。

必?cái)↑c(diǎn)和必勝點(diǎn)滿足的性質(zhì):

(1)終結(jié)點(diǎn)是必?cái)↑c(diǎn)

(2)可以進(jìn)行一次操作到達(dá)必?cái)↑c(diǎn)的為必勝點(diǎn)

(3)從必?cái)↑c(diǎn)只能到達(dá)必勝點(diǎn)

介紹SG函數(shù)前先介紹一下mex函數(shù),表示最小的不屬于這個(gè)集合的非負(fù)整數(shù),比如mex{0,1,3,4}=2,mex{1,2,3}=0;

任何一個(gè)可以用SG函數(shù)解決的問題都可以抽象成一個(gè)有向圖游戲,SG函數(shù)是用于為這種有向圖游戲提供最優(yōu)策略的。(SG(x)=0代表x為必?cái)B(tài),SG(x)!=0代表x為必勝態(tài))

對于給定游戲規(guī)則下的有向無環(huán)圖,定義SG(x)=mex{SG(y) | y是x的后繼}

容易知道終止?fàn)顟B(tài)的SG值一定是0,對于一個(gè)x滿足SG(x)=0,則對于x的所有后繼(經(jīng)過一次操作可到達(dá)的狀態(tài))y一定有SG(y)!=0,類似的,對于一個(gè)x滿足SG(x)!=0,則對于x的所有后繼y均有SG(y)==0。

頂點(diǎn)SG值的意義:

當(dāng)SG(x)=k時(shí),表明對于任何一個(gè)0<=i<k,都存在x的一個(gè)后繼y滿足SG(y)=i。

下面給出常見博弈論的解題方法:
把原問題按照游戲規(guī)則的差別分解成多個(gè)獨(dú)立的子游戲,并計(jì)算每個(gè)子游戲下的SG值,最后求出所有子游戲的SG值的異或

最后給出SG值的計(jì)算方法:

(1)若可選步數(shù)為1~m的連續(xù)整數(shù)(巴什博弈),則SG(x)=x%(m+1)

(2)若可選步數(shù)為任意步,則SG(x)=x

(3)剩余的情況只能具體問題具體分析了,下面給出求SG的函數(shù)模板

打表計(jì)算SG值

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int N=1e3+10;//具體數(shù)據(jù) int f[N],sg[N],vis[N]; //f[]記錄可以進(jìn)行的操作(比如取走多少個(gè)石子) //sg[]記錄每種狀態(tài)的sg值 //vis[x]用于標(biāo)記出現(xiàn)過的x的后繼的sg值 void SG(int n) {memset(sg,0,sizeof sg);//0是終止?fàn)顟B(tài)(必?cái)B(tài)),所以sg[0]一定為0 for(int i=1;i<=n;i++){memset(vis,0,sizeof vis);for(int j=1;f[j]<=i;j++)vis[sg[i-f[j]]]=1;//i-f[j]是狀態(tài)i進(jìn)行一次操作可以到達(dá)的狀態(tài) for(int j=0;j<=n;j++)//求解i的后繼的sg值中未出現(xiàn)的最小自然數(shù) {if(!vis[j]){sg[i]=j;break;}} } }

dfs計(jì)算SG值

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int N=1e3+10;//具體數(shù)據(jù) int f[N],sg[N],vis[N]; //f[]記錄可以進(jìn)行的操作(比如取走多少個(gè)石子) //sg[]記錄每種狀態(tài)的sg值 //vis[x]用于標(biāo)記出現(xiàn)過的x的后繼的sg值 int SG(int x) {//因?yàn)閟g值可能取到1,所以應(yīng)該初始化sg數(shù)組為-1 if(sg[x]!=-1) return sg[x];memset(vis,0,sizeof vis);for(int i=0;i<n;i++){if(x>=f[i]){SG(x-f[i]);vis[sg[x-f[i]]]=1;}}int e;for(int i=0;;i++){if(!vis[i]){e=i;break;}}return sg[x]=e; }

總結(jié)

以上是生活随笔為你收集整理的SG函数详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。