• 数学&搜索:博弈论之极大极小搜索与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
    ",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
    ",mp[0]);
    58     return 0;
    59 }
  • 相关阅读:
    实用的网站记录
    XML记一次带命名空间的xml读取
    WEB项目挂载到IIS session过期
    【EF】CodeFirst Fluent API使用记录
    【Unity】微软的一款依赖注入组件
    【AutoFac】依赖注入和控制反转的使用
    【JavaScript】封装实用方法【持续积累】
    【Config】类库读取自己的配置文件,配置文件的扩展
    【c#】队列(Queue)和MSMQ(消息队列)的基础使用
    0、Java配置----JDK开发环境搭建及环境变量配置
  • 原文地址:https://www.cnblogs.com/aininot260/p/9629874.html
Copyright © 2020-2023  润新知