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;
}
一共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;
}
相关文章推荐
- 博弈搜索练习-极大极小值搜索+AlphaBeta剪枝--POJ 1085-Triangle War/三角点格棋
- POJ - 1568 Find the Winning Move 极小极大搜索+alpha-beta剪枝
- poj1568 Find the Winning Move[极大极小搜索+alpha-beta剪枝]
- POJ 1568 极大极小搜索 + alpha-beta剪枝
- POJ 1568 Find the Winning Move(极小极大搜索+alpha-beta剪枝)
- 基于极大极小算法和alpha-beta剪枝实现AI井字棋
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- 转:极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- POJ 1085 Triangle War 博弈 (对抗搜索 alpha-beta 剪枝)
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- POJ - 3317 Stake Your Claim 极大极小搜索+alpha-beta剪枝+记忆化搜索
- 极小极大值方法以及alpha-Beta剪枝
- POJ 1568 Find the Winning Move 极大极小搜索+alpha-beta剪枝 -
- 极小极大搜索方法、负值最大算法和Alpha-Beta搜索方法
- 博弈(alpha-beta 剪枝)—— POJ 1568 Find the Winning Move
- 博弈(alpha-beta 剪枝)POJ —— 1085 Triangle War
- 极小极大搜索 的个人理解(alpha-beta剪枝)