树上博弈

一棵点权树,两人从根开始,一次选点,每个人只能选择上一个选点的子节点,两人策略不同。先手:让后手尽可能小前提下自己取值尽可能大;后手:自己取值尽量大的前提下让后手取值尽量小。先手从根开始取值,求先手与后手取值最终分别为多少。

关键词:树上博弈、最大-最小博弈

做法:由于决策考虑到先手和后手问题,因此必须增加一维状态,分别存储后手和先手的取值。

F[MAXN][2],F[i][0]表示以i为根的子树的先手最优值,F[i][1]表示以i为根的子树的后手最优值。

技巧:深度为奇数:先手;深度为偶数:后手

#include<stdio.h>
#include<iostream>
#include<string.h>
#define ll long long
#define maxn 1000010
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

int n;
int num[maxn],du[maxn];
struct Edge{
    int to,next;
}edge[maxn];
int head[maxn],tot,root;
int dp[maxn][3];

void add(int u,int v){
    edge[tot].to=v,edge[tot].next=head[u],head[u]=tot++;
}

void dfs(int u,int d){
    int tmp1=-100,k=-1,tmp2=INF;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        dfs(v,d+1);
        if(d&1){
            if(dp[v][0]>tmp1||(dp[v][0]==tmp1&&dp[v][1]<tmp2)) { tmp1=dp[v][0],tmp2=dp[v][1],k=v; }
        }
        else{
            if(dp[v][1]<tmp2||(dp[v][1]==tmp2&&dp[v][0]>tmp1)) { tmp2=dp[v][1],tmp1=dp[v][0],k=v; }
        }
    }
    dp[u][0]=num[u]+dp[k][1],dp[u][1]=dp[k][0];
}

int main(){
    //freopen("a.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&num[i]);
    mem(head,-1),tot=0,mem(du,0);
    for(int i=0;i<n-1;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        du[b]++;
        add(a,b);
    }
    for(int i=1;i<=n;i++) if(!du[i]) { root=i,dfs(i,1);break; }
    printf("%d %d\n",dp[root][0],dp[root][1]);
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Python代码,实现了博弈树五子棋的基本逻辑,包括棋盘的初始化、落子、判断胜负等操作。 ```python import numpy as np # 棋盘大小 BOARD_SIZE = 15 # 棋子类型 EMPTY = 0 BLACK = 1 WHITE = 2 # 胜利条件 WIN_CONDITION = 5 # 初始化棋盘 board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=np.int) # 判断是否胜利 def is_win(player): for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if board[i][j] == player: # 水平方向 if j + WIN_CONDITION <= BOARD_SIZE and np.all(board[i][j:j+WIN_CONDITION] == player): return True # 垂直方向 if i + WIN_CONDITION <= BOARD_SIZE and np.all(board[i:i+WIN_CONDITION, j] == player): return True # 左上到右下方向 if i + WIN_CONDITION <= BOARD_SIZE and j + WIN_CONDITION <= BOARD_SIZE and np.all(np.diag(board[i:i+WIN_CONDITION, j:j+WIN_CONDITION]) == player): return True # 右上到左下方向 if i + WIN_CONDITION <= BOARD_SIZE and j - WIN_CONDITION >= -1 and np.all(np.diag(np.fliplr(board[i:i+WIN_CONDITION, j-WIN_CONDITION+1:j+1])) == player): return True return False # 落子 def make_move(player, row, col): if board[row][col] == EMPTY: board[row][col] = player return True else: return False # 打印棋盘 def print_board(): for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if board[i][j] == EMPTY: print(".", end=" ") elif board[i][j] == BLACK: print("X", end=" ") elif board[i][j] == WHITE: print("O", end=" ") print() # 游戏循环 player = BLACK while True: print_board() row = int(input("请输入行号:")) col = int(input("请输入列号:")) if make_move(player, row, col): if is_win(player): print_board() print("player %d win!" % player) break player = WHITE if player == BLACK else BLACK else: print("该位置已有棋子,请重新输入!") ``` 这个代码只是实现了一个简单的人机对战,想要实现更复杂的博弈树算法,需要考虑更多的因素,比如搜索深度、评估函数等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值