poj 1085 Triangle War 极大极小搜索

9 篇文章 0 订阅
2 篇文章 0 订阅

Description


给定一个三角形矩阵如下
这里写图片描述
两个人每次每人可以把一条虚线涂黑,若操作后的一条边与另外两条邻边形成一个三角形就能再操作一次,每次操作的得分为此次操作形成的新的三角形。现在给定一些已经走了的操作求谁会赢,假设两人绝对聪明

Solution


裸的极大极小搜索了。一开始以为做成一个三角形就结束了

我看很多题解说要压缩状态但是好像不用也可以

这里的alphabeta可能打反了,可是不影响理解

Code


#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;i+=1)
#define fill(x,t) memset(x,t,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f
#define N 21

struct edge{int x,y;}e[N];
int rc[N][N],id[N][N],A;
int edgeCnt;

int read() {
    int x=0; char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x;
}

void addEdge(int x,int y) {
    e[++edgeCnt]=(edge){x,y};
}

bool isTriangle(int x,int y,int z) {
    return rc[x][y]&&rc[y][z]&&rc[x][z];
}

int check() {
    int ret=0;
    ret+=isTriangle(1,2,3)+isTriangle(2,4,5)+isTriangle(2,3,5);
    ret+=isTriangle(3,5,6)+isTriangle(4,7,8)+isTriangle(4,5,8);
    ret+=isTriangle(5,8,9)+isTriangle(5,6,9)+isTriangle(6,9,10);
    return ret;
}

int findMin(int dep,int alpha);

int findMax(int dep,int beta) {
    if (dep==18) return ((A)>(0)?(INF):(-INF));
    int ret=-INF;
    int record=check();
    rep(i,1,edgeCnt) {
        if (!rc[e[i].x][e[i].y]) {
            rc[e[i].x][e[i].y]=rc[e[i].y][e[i].x]=1;
            int now=check(),val;
            A+=now-record;

            if (now-record>0) val=findMax(dep+1,beta);
            else val=findMin(dep+1,ret);

            A-=now-record;
            rc[e[i].x][e[i].y]=rc[e[i].y][e[i].x]=0;
            ret=max(ret,val);
            if (ret>=beta) return ret;
        }
    }
    return ret;
}

int findMin(int dep,int alpha) {
    if (dep==18) return ((A)>(0)?(INF):(-INF));
    int ret=INF;
    int record=check();
    rep(i,1,edgeCnt) {
        if (!rc[e[i].x][e[i].y]) {
            rc[e[i].x][e[i].y]=rc[e[i].y][e[i].x]=1;
            int now=check(),val;
            A-=now-record;

            if (now-record>0) val=findMin(dep+1,alpha);
            else val=findMax(dep+1,ret);

            A+=now-record;
            rc[e[i].x][e[i].y]=rc[e[i].y][e[i].x]=0;
            ret=min(val,ret);
            if (ret<=alpha) return ret;
        }
    }
    return ret;
}

void init() {
    addEdge(1,2);
    addEdge(1,3);
    addEdge(2,3);
    addEdge(2,4);
    addEdge(2,5);
    addEdge(3,5);
    addEdge(3,6);
    addEdge(4,5);
    addEdge(5,6);
    addEdge(4,7);
    addEdge(4,8);
    addEdge(5,8);
    addEdge(5,9);
    addEdge(6,9);
    addEdge(6,10);
    addEdge(7,8);
    addEdge(8,9);
    addEdge(9,10);
}
int main(void) {
    init();
    int T=read();
    int game=0;
    while (T--) {
        fill(rc,0);
        A=0;
        int n=read();
        int last=0,now=0;
        int person=1;
        rep(i,1,n) {
            int x=read();
            int y=read();
            rc[x][y]=rc[y][x]=1;
            now=check();
            if (person) {
                A+=now-last;
            } else {
                A-=now-last;
            }
            if (now==last) {
                person^=1;
            }
            last=now;
        }
        int ans;
        if (person) {
            ans=findMax(n,INF);
        } else {
            ans=findMin(n,-INF);
        }
        if (ans==INF) {
            printf("Game %d: A wins.\n", ++game);
        } else {
            printf("Game %d: B wins.\n", ++game);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值