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;
}