数学&搜索:博弈论之极大极小搜索与alpha-beta减枝

目的是寻找最优的方案使得自己能够利益最大化。

基本思想就是假设自己(A)足够聪明,总是能选择最有利于自己的方案,而对手(B)同样足够聪明,总会选择最不利A的方案

对抗搜索就是对于先手来说,取后手中状态最大的;对于后手来说,取终态中状态最小的

对于第一个人

它一定从当前局面可以到达的所有局面中,选择一个最大的走

第二个人一定会从当前局面所有可以到达的局面中,选择一个最小的走

省选第一题一双木棋

正解是博弈论记忆化搜索+状态压缩

然而我这里先贴一份纯对抗搜索的代码

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 bool vis[12][12];
 5 int a[12][12],b[12][12];
 6 int col[12][12];
 7 int n,m;
 8 struct node{
 9     int ans1,ans2;
10 };
11 node dfs(int num,int f)
12 {
13     if(num==n*m)
14     {
15         int ans1=0,ans2=0;
16         for(int i=1;i<=n;i++)
17          for(int j=1;j<=m;j++)
18           {
19             if(col[i][j]==1) ans1+=a[i][j];
20             if(col[i][j]==2) ans2+=b[i][j];
21           }
22         return (node){ans1,ans2};
23     }
24    node ans;
25    int maxi=-1e9+7;
26    for(int i=1;i<=n;i++)
27     for(int j=1;j<=m;j++)
28      {
29         if(vis[i-1][j]||(i-1==0))
30          if(vis[i][j-1]||(j-1==0))
31           if(!vis[i][j])
32           {
33             vis[i][j]=1;
34             col[i][j]=f;
35             node dx=dfs(num+1,f==1?2:1);
36             vis[i][j]=0;
37             col[i][j]=0;
38             int ansx=f==1?dx.ans1-dx.ans2:dx.ans2-dx.ans1;
39             if(ansx>maxi) maxi=ansx,ans=dx;
40           }
41      }
42     return ans;
43 }
44 int main()
45 {
46     //freopen("chess.in","r",stdin);
47     //freopen("chess.out","w",stdout);
48     scanf("%d%d",&n,&m);
49     for(int i=1;i<=n;i++)
50      for(int j=1;j<=m;j++)
51       scanf("%d",&a[i][j]);
52     for(int i=1;i<=n;i++)
53      for(int j=1;j<=m;j++)
54       scanf("%d",&b[i][j]);
55     node ans=dfs(0,1);
56     printf("%d\n",ans.ans1-ans.ans2);
57     return 0;
58 }

然后是状态压缩+记忆化

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <map>
 4 #define ll long long
 5 #define inf 0x7fffffff
 6 std::map <ll,int> mp;
 7 ll end;
 8 int n,m;
 9 int num[20],a[20][20],b[20][20];
10 inline int unzip(ll sta)
11 {
12     int s=0;
13     for(int i=n;i;i--) s+=(num[i]=(sta%(m+1))),sta/=(m+1);
14     return s&1;
15 }
16 inline ll zip()
17 {
18     ll s=0;
19     for(int i=1;i<=n;i++) s=s*(m+1)+num[i];
20     return s;
21 }
22 int DFS(ll sta)
23 {
24     if(mp.find(sta)!=mp.end()) return mp[sta];
25     if(sta==end) return 0;
26     int opt=unzip(sta);
27     int ans=opt?inf:-inf;
28     if(num[1]<m)
29     {
30         ++num[1];
31         if(opt) ans=std::min(ans,DFS(zip())-b[1][num[1]]);
32         else ans=std::max(ans,DFS(zip())+a[1][num[1]]);
33         --num[1];
34     }
35     for(int i=2;i<=n;i++)
36      if(num[i-1]>num[i])
37      {
38         ++num[i];
39         if(opt) ans=std::min(ans,DFS(zip())-b[i][num[i]]);
40         else ans=std::max(ans,DFS(zip())+a[i][num[i]]);
41         --num[i];
42      }
43     return mp[sta]=ans;
44 }
45 int main()
46 {
47     scanf("%d%d",&n,&m);
48     for(int i=1;i<=n;i++)
49      for(int j=1;j<=m;j++)
50       scanf("%d",&a[i][j]);
51     for(int i=1;i<=n;i++)
52      for(int j=1;j<=m;j++)
53       scanf("%d",&b[i][j]);
54     for(int i=1;i<=n;i++) num[i]=m;
55     end=zip();
56     DFS(0);
57     printf("%d\n",mp[0]);
58     return 0;
59 }

 

posted @ 2018-09-11 19:51  静听风吟。  阅读(535)  评论(0编辑  收藏  举报