您的位置:首页 > 其它

POJ - 1085 Triangle War 极小极大搜索+alpha-beta剪枝

2017-10-01 23:10 561 查看
题目:有一个这样的图形



一共10个顶点,有A,B两个玩家,A先手,每次每个玩家可以选择连接2个相邻但是没连接的顶点,构成的三角形属于当前操作者,并且可以额外再操作一次,谁拥有的三角形数目多谁胜。给出前面的一些操作,问你是A胜还是B胜

思路:极小极大搜索+alpha-beta剪枝

给两个相邻顶点的边编个号,一共有18条边分别编号为0~17,9个三角形,可以用三角形的三条边的二进制和表示

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
//0x3f3f3f3f

//对10个顶点之间的边的编号0~17
int idx[11][11]={
{0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,2,3,4,0,0,0,0,0},
{0,1,2,0,0,5,6,0,0,0,0},
{0,0,3,0,0,7,0,9,10,0,0},
{0,0,4,5,7,0,8,0,11,12,0},
{0,0,0,6,0,8,0,0,0,13,14},
{0,0,0,0,9,0,0,0,15,0,0},
{0,0,0,0,10,11,0,15,0,16,0},
{0,0,0,0,0,12,13,0,16,0,17},
{0,0,0,0,0,0,14,0,0,17,0}
};
//用三角形的3各顶点的二进制和代表每个三角形
int tri[9]={7,152,52,352,34304,3200,71680,12544,155648};
int End=(1<<18)-1;
int get_status(int old,int seg,int &num){
int now=old|seg;
for(int i=0;i<9;i++)
if((old&tri[i])!=tri[i]&&(now&tri[i])==tri[i])
num++;
return now;
}
int MaxSearch(int state,int alpha,int ca,int cb);
int MinSearch(int state,int beta,int ca,int cb);
int MinSearch(int state,int beta,int ca,int cb){
if(ca>=5) return 1;//A赢了
if(cb>=5) return -1;//B赢了
if(state==End) return ca>cb?1:-1;
int remain=(~state)&End;
int ans=1;
while(remain){
int seg=remain&(-remain);
int ta=ca,tb=cb;
int now=get_status(state,seg,tb);
int tmp;
if(tb>cb) tmp=MinSearch(now,beta,ta,tb);//形成一个三角形可以多一个回合
else tmp=MaxSearch(now,ans,ta,tb);
if(ans>tmp) ans=tmp;
if(ans<=beta) return ans;
remain-=seg;
}
return ans;
}
int MaxSearch(int state,int alpha,int ca,int cb){
if(ca>=5) return 1;//A赢了
if(cb>=5) return -1;//B赢了
if(state==End) return ca>cb?1:-1;
int remain=(~state)&End;
int ans=-1;
while(remain){
int seg=remain&(-remain);
int ta=ca,tb=cb;
int now=get_status(state,seg,ta);
int tmp;
if(ta>ca) tmp=MaxSearch(now,alpha,ta,tb);
else tmp=MinSearch(now,ans,ta,tb);
if(ans<tmp) ans=tmp;
if(ans>=alpha) return ans;
remain-=seg;
}
return ans;
}
int main(){

// freopen("D:\\input.txt","r",stdin);
// freopen("D:\\output.txt","w",stdout);
int T,cas=0,n,a,b;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int staus=0,ca=0,cb=0,pos=0;
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
int ta=ca,tb=cb;
if(pos%2==0)
staus=get_status(staus,(1<<idx[a][b]),ca);
else
staus=get_status(staus,(1<<idx[a][b]),cb);
if(ta==ca&&tb==cb)
pos++;
}
int ans;
if(pos%2==0) ans=MaxSearch(staus,1,ca,cb);
else ans=MinSearch(staus,-1,ca,cb);
if(ans==1)
printf("Game %d: A wins.\n",++cas);
else
printf("Game %d: B wins.\n",++cas);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: