有兩條蛇(1號蛇和2號蛇)在n行m列的地圖上,地圖上有障礙物。一條蛇碰到蛇身/障礙物/邊界就會死。蛇身會不斷長長——可以理解為蛇尾位置不會變,蛇只會向前伸展不會縮尾巴。兩條蛇都絕頂聰明,如果自己能贏,一定會盡量快地贏;如果自己會輸,一定會死得盡量晚。給出初始局面,兩蛇輪流走,每次可以且必須向上下左右移動一格。1號蛇先走,請告訴我誰會在多少回合時贏。\((n,m\leq 20)\)且\(0\)的數量不超過\(50\)
前提:雙方絕頂聰明,各自為營
用我的話來說,這個剪枝方法是這樣的乙個結構:
所有的估價都是由同乙個角度來看待的,不能說在1的回合說對1有利,在2的回合又說對2有利(應該說對1有害)
搜尋樹上先手通過一條邊轉移成後手
搜尋樹的葉子節點是估價函式,評估到達的這個狀態的好壞,函式值越大對先手越有利,父親節點的權值均由兒子轉移來
奇偶性不同的層求的東西不一樣,即兩個人的策略不同,先手求的是所有兒子中最大的乙個(即對先手最有利),後手求的是最小的乙個(對先手最有害)
總而言之,就是搜尋樹的奇數層節點取\(max\),偶數層取\(min\),葉子節點需要自己估價(根據具體的題目)
扯了半天,如何剪枝?很簡單,比如對於先手節點\(u\),它會取最大的兒子,假設當前權值為\(ans_u\),如果當前節點的兒子\(v\)的乙個兒子\(vv\)權值小於\(ans_u\),就不用再遍歷這個兒子\(v\)剩下的兒子了(因為兒子\(v\)的權值取\(min\)),這個兒子\(v\)的權值到目前為止可以判斷一定小於\(ans_u\)了;後手相反(可能會有點抽象,建議畫圖理解)
本題顯然可以用\(\alpha - \beta\)剪枝(雙方絕頂聰明且操縱的蛇不一樣)
主要是估價函式的設計:如果先手無路可走,就是絕對有害,設為\(-inf\),但又活的越久越好,所以還要加上乙個存活時間\(step\),後手同理
這個剪枝還是比較簡單好理解的,主要注意不要把先後大小關係搞反了就行
#include#define n 25
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
const int inf = 10000;
int n,m,a[n][n],sx[2],sy[2];
int dox[4]=,doy[4]=;
template void read(t &x)
int dfs(int step,int player,int alpha,int beta,int fx,int fy,int px,int py)//alpha是下界只降不增,beta是上界只增不降
else//它的父親是先手,和上面討論的一致
}if(!flag)//移動不了,即到了葉子(輸),需要估價
return ans;
}int main()
int ans=dfs(1,1,inf,-inf,sx[0],sy[0],sx[1],sy[1]);
if(ans>0) printf("1 %d\n",inf-ans);//最後到達的是2號對應的葉子,減掉inf還原
else printf("2 %d\n",ans+inf);//最後到達的是1號對應的葉子,加上inf(這個見上面dfs中估價函式的計算)
return 0;
}
\(learning from\):部落格1,部落格2
p.s. 筆者小白一枚,如有錯誤還請指出
貪吃蛇遊戲
貪吃蛇遊戲 結構化程式設計 c語言程式設計 重要的的是結構化的程式設計思想 include include include include include include define field width 300 就做20個格仔的 define field height 300 define f...
貪吃蛇(改進)
該程式分成3個檔案 第乙個檔案 fang.cs using system using system.collections.generic using system.text using system.windows.forms using system.drawing namespace snak...
貪吃蛇遊戲
include include include include include 使用當前時間做種子 enum dir 列舉型別enum dir 圍牆 class fencef 定義物件 畫框框 void fence initfence 顯示框框 void fence outputf int snak...