2019年4月17日更新:

将搜索主函数优化为局部记忆化搜索,再次提高若干倍搜索速度

更新了main和player,helper无更新

 #include "Player-v3.0.cpp"
#include "Helper.cpp" #define END {if(fir){newA=a; newB=b;} return 1;}
#define NXT {if(ok&&play(b,a,0)==0) return 1; else return 0;}
#define NO {printf("Can't Out\n"); newA=a; newB=b;}
player newA,newB;
bool play(player,player,bool); bool Play_Rocket(player a,player b,bool fir){
if(b.empty()) return ;
if(a.CanPlayRocket()){
a.PlayRocket();
bool now=play(a,b,);
if(now){
if(fir) Out_Rocket();
END;
}
}
return ;
} bool Play_Boom(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
if(Play_Rocket(a,b,fir)) return ;
player _a=a;
if(a.CanBoom)
for(int i=last+;i<;i++)
if(a.CanPlayBoom(i)){
a.PlayBoom(i);
a.ResetCan();
bool now=Play_Boom(b,a,i,,);
if(!now){
if(fir) Out_Boom(i);
END;
}
a=_a;
}
NXT;
} bool Play_Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlaySingle(i)){
a.PlaySingle(i);
bool now=Play_Single(b,a,i,,);
if(!now){
if(fir) Out_Single(i);
END;
}
a=_a;
}
NXT;
} bool Play_Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlayCouple(i)){
a.PlayCouple(i);
bool now=Play_Couple(b,a,i,,);
if(!now){
if(fir) Out_Couple(i);
END;
}
a=_a;
}
NXT;
} bool Play_Three(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanThree)
for(int i=last+;i<;i++)
if(a.CanPlayThree(i)){
a.PlayThree(i);
a.ResetCan();
bool now=Play_Three(b,a,i,,);
if(!now){
if(fir) Out_Three(i);
END;
}
a=_a;
}
NXT;
} bool Play_3Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
if(a.CanThree)
for(int j=;j<;j++)
if(a.CanPlay3Single(i,j)){
a.Play3Single(i,j);
a.ResetCan();
bool now=Play_3Single(b,a,i,,);
if(!now){
if(fir) Out_3Single(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_3Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
if(a.CanThree)
for(int j=;j<;j++)
if(a.CanPlay3Couple(i,j)){
a.Play3Couple(i,j);
a.ResetCan();
bool now=Play_3Couple(b,a,i,,);
if(!now){
if(fir) Out_3Couple(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_4Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
if(a.CanBoom)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Single(i,j,k)){
a.Play4Single(i,j,k);
a.ResetCan();
bool now=Play_4Single(b,a,i,,);
if(!now){
if(fir) Out_4Single(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_4Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
if(a.CanBoom)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Couple(i,j,k)){
a.Play4Couple(i,j,k);
a.ResetCan();
bool now=Play_4Couple(b,a,i,,);
if(!now){
if(fir) Out_4Couple(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_MS(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanMS)
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreSingle(i,i+pls)){
a.PlayMoreSingle(i,i+pls);
a.ResetCan();
bool now=Play_MS(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MS(i,i+pls);
END;
}
a=_a;
}
NXT;
} bool Play_MC(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanMC)
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreCouple(i,i+pls)){
a.PlayMoreCouple(i,i+pls);
a.ResetCan();
bool now=Play_MC(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MC(i,i+pls);
END;
}
a=_a;
}
NXT;
} map<pair<long long,long long>,int> Visit;
bool play(player a,player b,bool fir=){
if(b.empty()) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.cnt+b.cnt<&&fir==){
if(Visit.count(make_pair(a.Hash(),b.Hash())))
return Visit[make_pair(a.Hash(),b.Hash())];
}
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.CanMS)
for(int i=;i>=;i--){
if(Play_MS(a,b,-,-+i,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
}
if(a.CanMC)
for(int i=;i>=;i--){
if(Play_MC(a,b,-,-+i,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
}
if(a.CanThree) if(Play_Three(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.CanThree) if(Play_3Single(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.CanThree) if(Play_3Couple(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(Play_Couple(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(Play_Single(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.CanBoom) if(Play_4Single(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
if(a.CanBoom) if(Play_4Couple(a,b,-,fir,)) return Visit[make_pair(a.Hash(),b.Hash())]=;
return Visit[make_pair(a.Hash(),b.Hash())]=;
} int Main(){
Visit.clear();
player a,b;
printf("INPUT AI:\n");
b.read();
printf("INPUT PLAYER:\n");
a.read();
int staT=clock();
if(!play(a,b,)){
printf("DIE\n");
return ;
}
printf("\nFirst Time Use %dms\n",clock()-staT);
while(){
a=newA; b=newB;
printf("\n");
if(a.empty()){
printf("WIN\n");
return ;
} string now; cin>>now;
if(now=="EXIT") return ;
if(Is_Empty(now)){
if(!play(a,b,)){
printf("DIE\n");
}
continue;
}
for(int i=;i<now.length();i++) b.PlaySingle(GetVal(now[i])); if(Is_Single(now)&&Play_Single(a,b,GetVal(now[]),,)==) NO;
if(Is_Couple(now)&&Play_Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_Three(now)&&Play_Three(a,b,GetVal(now[]),,)==) NO;
if(Is_Boom(now)&&Play_Boom(a,b,GetVal(now[]),,)==) NO;
if(Is_Rocket(now)&&Play_Rocket(a,b,)==) NO;
if(Is_3Single(now)&&Play_3Single(a,b,GetVal(now[]),,)==) NO;
if(Is_3Couple(now)&&Play_3Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_4Single(now)&&Play_4Single(a,b,GetVal(now[]),,)==) NO;
if(Is_4Couple(now)&&Play_4Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_MS(now)&&Play_MS(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
if(Is_MC(now)&&Play_MC(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
}
} int main(){
while() Main();
}

main-v3.0

 /*
???????????????????
??
??????
*/ #include<bits/stdc++.h>
using namespace std; int GetVal(char c){
if(c=='T') return ;
if(c=='J') return ;
if(c=='Q') return ;
if(c=='K') return ;
if(c=='A') return ;
if(c=='') return ;
if(c=='w') return ;
if(c=='W') return ;
if(''<=c&&c<='') return c-'';
assert();
}
char SetChar(int x){
if(x<=) return ''+x;
if(x==) return 'T';
if(x==) return 'J';
if(x==) return 'Q';
if(x==) return 'K';
if(x==) return 'A';
if(x==) return '';
if(x==) return 'w';
if(x==) return 'W';
assert();
} struct player{
int a[],cnt;
bool CanThree,CanBoom,CanMS,CanMC;
player(){memset(a,,sizeof(a));cnt=;} void out(){//Output Poker
for(int i=;i<;i++)
for(int j=;j<a[i];j++)
putchar(SetChar(i));
putchar('\n');
} inline bool CanPlaySingle(int x){return a[x]>=;}//? inline bool CanPlayCouple(int x){return a[x]>=;}//? inline bool CanPlayThree(int x){return a[x]>=;}//?? inline bool CanPlayBoom(int x){return a[x]>=;}//?? inline bool CanPlayRocket(){return a[]&&a[];}//?? inline bool CanPlayMoreSingle(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlaySingle(i)) return ;
return ;
} inline bool CanPlayMoreCouple(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayCouple(i)) return ;
return ;
} inline bool CanPlayMoreThree(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayThree(i)) return ;
return ;
} inline bool CanPlay4Single(int x,int l,int r){//???
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayCouple(l);
return CanPlayBoom(x)&&CanPlaySingle(l)&&CanPlaySingle(r);
} inline bool CanPlay4Couple(int x,int l,int r){//???
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayBoom(l);
return CanPlayBoom(x)&&CanPlayCouple(l)&&CanPlayCouple(r);
} inline bool CanPlay3Single(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlaySingle(y);
} inline bool CanPlay3Couple(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlayCouple(y);
} inline void PlaySingle(int x){a[x]--; cnt--;} inline void PlayCouple(int x){a[x]-=; cnt-=;} inline void PlayThree(int x){a[x]-=; cnt-=;} inline void PlayBoom(int x){a[x]-=; cnt-=;} inline void PlayRocket(){a[]--;a[]--; cnt-=;} inline void PlayMoreSingle(int l,int r){for(int i=l;i<=r;i++) PlaySingle(i);} inline void PlayMoreCouple(int l,int r){for(int i=l;i<=r;i++) PlayCouple(i);} inline void PlayMoreThree(int l,int r){for(int i=l;i<=r;i++) PlayThree(i);} inline void Play4Single(int x,int l,int r){PlayBoom(x); PlaySingle(l); PlaySingle(r);} inline void Play4Couple(int x,int l,int r){PlayBoom(x); PlayCouple(l); PlayCouple(r);} inline void Play3Single(int x,int y){PlayThree(x); PlaySingle(y);} inline void Play3Couple(int x,int y){PlayThree(x); PlayCouple(y);} inline bool empty(){
return cnt==;
}//?????? inline long long Hash(){long long res=; for(int i=;i<;i++) res=res<<|a[i]; return res;}//??? inline int GetMin(){for(int i=;i<;i++) if(a[i]) return i; assert();}
inline int GetMax(){for(int i=;~i;i--) if(a[i]) return i; return -;} inline void ResetCan(){
CanThree=CanBoom=CanMS=CanMC=;//!!!
for(int i=;i<;i++){
if(CanPlayThree(i)) CanThree=;
if(CanPlayBoom(i)) CanBoom=;
}
if(CanPlayRocket()) CanBoom=;
for(int i=;i<=;i++){
if(CanPlayMoreSingle(i,i+)) {CanMS=; break;}
}
for(int i=;i<=;i++){
if(CanPlayMoreCouple(i,i+)) {CanMC=; break;}
}
} void read(){//Input Poker
memset(a,,sizeof(a)); cnt=;
string s; cin>>s; int len=s.length(); cnt=len;
for(int i=;i<len;i++)
a[GetVal(s[i])]++;
ResetCan();
}
};

Player-v3.0

3.0版本在双方牌数不大于15张时,基本可以在1s内出解

(OFast编译,CPU:I5-4210M,辣鸡CPU)

2019年4月16日更新:

优化了分支判断速度,快了若干倍

更新了main和player,helper无更新

 #include "Player-v2.0.cpp"
#include "Helper.cpp" #define END {if(fir){newA=a; newB=b;} return 1;}
#define NXT {if(ok&&play(b,a,0)==0) return 1; else return 0;}
#define NO {printf("Can't Out\n"); newA=a; newB=b;}
player newA,newB;
bool play(player,player,bool); bool Play_Rocket(player a,player b,bool fir){
if(b.empty()) return ;
if(a.CanPlayRocket()){
a.PlayRocket();
bool now=play(a,b,);
if(now){
if(fir) Out_Rocket();
END;
}
}
return ;
} bool Play_Boom(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
if(Play_Rocket(a,b,fir)) return ;
player _a=a;
if(a.CanBoom)
for(int i=last+;i<;i++)
if(a.CanPlayBoom(i)){
a.PlayBoom(i);
a.ResetCan();
bool now=Play_Boom(b,a,i,,);
if(!now){
if(fir) Out_Boom(i);
END;
}
a=_a;
}
NXT;
} bool Play_Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlaySingle(i)){
a.PlaySingle(i);
bool now=Play_Single(b,a,i,,);
if(!now){
if(fir) Out_Single(i);
END;
}
a=_a;
}
NXT;
} bool Play_Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlayCouple(i)){
a.PlayCouple(i);
bool now=Play_Couple(b,a,i,,);
if(!now){
if(fir) Out_Couple(i);
END;
}
a=_a;
}
NXT;
} bool Play_Three(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanThree)
for(int i=last+;i<;i++)
if(a.CanPlayThree(i)){
a.PlayThree(i);
a.ResetCan();
bool now=Play_Three(b,a,i,,);
if(!now){
if(fir) Out_Three(i);
END;
}
a=_a;
}
NXT;
} bool Play_3Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
if(a.CanThree)
for(int j=;j<;j++)
if(a.CanPlay3Single(i,j)){
a.Play3Single(i,j);
a.ResetCan();
bool now=Play_3Single(b,a,i,,);
if(!now){
if(fir) Out_3Single(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_3Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
if(a.CanThree)
for(int j=;j<;j++)
if(a.CanPlay3Couple(i,j)){
a.Play3Couple(i,j);
a.ResetCan();
bool now=Play_3Couple(b,a,i,,);
if(!now){
if(fir) Out_3Couple(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_4Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
if(a.CanBoom)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Single(i,j,k)){
a.Play4Single(i,j,k);
// a.ResetCan();
bool now=Play_4Single(b,a,i,,);
if(!now){
if(fir) Out_4Single(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_4Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
if(a.CanBoom)
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Couple(i,j,k)){
a.Play4Couple(i,j,k);
a.ResetCan();
bool now=Play_4Couple(b,a,i,,);
if(!now){
if(fir) Out_4Couple(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_MS(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanMS)
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreSingle(i,i+pls)){
a.PlayMoreSingle(i,i+pls);
a.ResetCan();
bool now=Play_MS(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MS(i,i+pls);
END;
}
a=_a;
}
NXT;
} bool Play_MC(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanMC)
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreCouple(i,i+pls)){
a.PlayMoreCouple(i,i+pls);
a.ResetCan();
bool now=Play_MC(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MC(i,i+pls);
END;
}
a=_a;
}
NXT;
} bool play(player a,player b,bool fir=){
if(b.empty()) return ;
if(a.CanBoom) if(Play_Boom(a,b,-,fir,)) return ;
if(a.CanMS)
for(int i=;i>=;i--){
if(Play_MS(a,b,-,-+i,fir,)) return ;
}
if(a.CanMC)
for(int i=;i>=;i--){
if(Play_MC(a,b,-,-+i,fir,)) return ;
}
if(a.CanThree) if(Play_Three(a,b,-,fir,)) return ;
if(a.CanThree) if(Play_3Single(a,b,-,fir,)) return ;
if(a.CanThree) if(Play_3Couple(a,b,-,fir,)) return ;
if(Play_Couple(a,b,-,fir,)) return ;
if(Play_Single(a,b,-,fir,)) return ;
if(a.CanBoom) if(Play_4Single(a,b,-,fir,)) return ;
if(a.CanBoom) if(Play_4Couple(a,b,-,fir,)) return ;
return ;
} int Main(){
player a,b;
printf("INPUT AI:\n");
b.read();
printf("INPUT PLAYER:\n");
a.read();
if(!play(a,b,)){
printf("DIE\n");
return ;
}
while(){
a=newA; b=newB;
printf("\n");
if(a.empty()){
printf("WIN\n");
return ;
} string now; cin>>now;
if(now=="EXIT") return ;
if(Is_Empty(now)){
if(!play(a,b,)){
printf("DIE\n");
}
continue;
}
for(int i=;i<now.length();i++) b.PlaySingle(GetVal(now[i])); if(Is_Single(now)&&Play_Single(a,b,GetVal(now[]),,)==) NO;
if(Is_Couple(now)&&Play_Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_Three(now)&&Play_Three(a,b,GetVal(now[]),,)==) NO;
if(Is_Boom(now)&&Play_Boom(a,b,GetVal(now[]),,)==) NO;
if(Is_Rocket(now)&&Play_Rocket(a,b,)==) NO;
if(Is_3Single(now)&&Play_3Single(a,b,GetVal(now[]),,)==) NO;
if(Is_3Couple(now)&&Play_3Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_4Single(now)&&Play_4Single(a,b,GetVal(now[]),,)==) NO;
if(Is_4Couple(now)&&Play_4Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_MS(now)&&Play_MS(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
if(Is_MC(now)&&Play_MC(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
}
} int main(){
while() Main();
}

main-v2.0

 /*
???????????????????
??
??????
*/ #include<bits/stdc++.h>
using namespace std; int GetVal(char c){
if(c=='T') return ;
if(c=='J') return ;
if(c=='Q') return ;
if(c=='K') return ;
if(c=='A') return ;
if(c=='') return ;
if(c=='w') return ;
if(c=='W') return ;
if(''<=c&&c<='') return c-'';
assert();
}
char SetChar(int x){
if(x<=) return ''+x;
if(x==) return 'T';
if(x==) return 'J';
if(x==) return 'Q';
if(x==) return 'K';
if(x==) return 'A';
if(x==) return '';
if(x==) return 'w';
if(x==) return 'W';
assert();
} struct player{
int a[];
bool CanThree,CanBoom,CanMS,CanMC;
player(){memset(a,,sizeof(a));} void out(){//Output Poker
for(int i=;i<;i++)
for(int j=;j<a[i];j++)
putchar(SetChar(i));
putchar('\n');
} inline bool CanPlaySingle(int x){return a[x]>=;}//? inline bool CanPlayCouple(int x){return a[x]>=;}//? inline bool CanPlayThree(int x){return a[x]>=;}//?? inline bool CanPlayBoom(int x){return a[x]>=;}//?? inline bool CanPlayRocket(){return a[]&&a[];}//?? inline bool CanPlayMoreSingle(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlaySingle(i)) return ;
return ;
} inline bool CanPlayMoreCouple(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayCouple(i)) return ;
return ;
} inline bool CanPlayMoreThree(int l,int r){//??
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayThree(i)) return ;
return ;
} inline bool CanPlay4Single(int x,int l,int r){//???
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayCouple(l);
return CanPlayBoom(x)&&CanPlaySingle(l)&&CanPlaySingle(r);
} inline bool CanPlay4Couple(int x,int l,int r){//???
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayBoom(l);
return CanPlayBoom(x)&&CanPlayCouple(l)&&CanPlayCouple(r);
} inline bool CanPlay3Single(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlaySingle(y);
} inline bool CanPlay3Couple(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlayCouple(y);
} inline void PlaySingle(int x){a[x]--;} inline void PlayCouple(int x){a[x]-=;} inline void PlayThree(int x){a[x]-=;} inline void PlayBoom(int x){a[x]-=;} inline void PlayRocket(){a[]--;a[]--;} inline void PlayMoreSingle(int l,int r){for(int i=l;i<=r;i++) PlaySingle(i);} inline void PlayMoreCouple(int l,int r){for(int i=l;i<=r;i++) PlayCouple(i);} inline void PlayMoreThree(int l,int r){for(int i=l;i<=r;i++) PlayThree(i);} inline void Play4Single(int x,int l,int r){PlayBoom(x); PlaySingle(l); PlaySingle(r);} inline void Play4Couple(int x,int l,int r){PlayBoom(x); PlayCouple(l); PlayCouple(r);} inline void Play3Single(int x,int y){PlayThree(x); PlaySingle(y);} inline void Play3Couple(int x,int y){PlayThree(x); PlayCouple(y);} inline bool empty(){
for(int i=;i<;i++)
if(a[i])
return ;
return ;}//?????? inline long long Hash(){long long res=; for(int i=;i<;i++) res=res<<|a[i]; return res;}//??? inline int GetMin(){for(int i=;i<;i++) if(a[i]) return i; assert();}
inline int GetMax(){for(int i=;~i;i--) if(a[i]) return i; return -;} inline void ResetCan(){
CanThree=CanBoom=CanMS=CanMC=;//!!!
for(int i=;i<;i++){
if(CanPlayThree(i)) CanThree=;
if(CanPlayBoom(i)) CanBoom=;
}
if(CanPlayRocket()) CanBoom=;
for(int i=;i<=;i++){
if(CanPlayMoreSingle(i,i+)) {CanMS=; break;}
}
for(int i=;i<=;i++){
if(CanPlayMoreCouple(i,i+)) {CanMC=; break;}
}
} void read(){//Input Poker
memset(a,,sizeof(a));
string s; cin>>s; int len=s.length();
for(int i=;i<len;i++)
a[GetVal(s[i])]++;
ResetCan();
}
};

Player-v2.0

众所周知欢乐斗地主这个游戏有一个叫做残局的模式

模式的特征:你和机器人都互相知道对方的牌,且对面的机器人绝顶聪明。

正常的斗地主规则,问你要如何出牌,才能保证你一定能赢。

我们考虑直接爆搜,发现需要搜一年。

于是我们加一个Alpha-Beta剪枝来加速整个爆搜过程即可。

貌似绝大部分情况下都是秒出结果的

目前最长时间只搜了15s(这是v2.0的时间,旧版貌似接近一分钟了)

正确率100%,快速通关利器233333

输入牌型要求:2~9直接输入,JQKA直接输入,10用T表示,大王小王分别用Ww表示。

输入顺子/连对要从小到大输入(按照斗地主规则的从小到大),输入三带一/对,四带二/对,需要先输入三张/四张,再输入剩下的东西

代码貌似只要10k多一点

注意细节

两个关联文件的代码:

 /*
该部分函数用于输出打出的牌
以及
分析当前输入的牌型 */ inline void Out_Single(int x){printf("%c",SetChar(x));} inline void Out_Couple(int x){printf("%c%c",SetChar(x),SetChar(x));} inline void Out_Three(int x){printf("%c%c%c",SetChar(x),SetChar(x),SetChar(x));} inline void Out_Boom(int x){printf("%c%c%c%c",SetChar(x),SetChar(x),SetChar(x),SetChar(x));} inline void Out_3Single(int x,int y){Out_Three(x); Out_Single(y);} inline void Out_3Couple(int x,int y){Out_Three(x); Out_Couple(y);} inline void Out_MS(int l,int r){for(int i=l;i<=r;i++) Out_Single(i);} inline void Out_MC(int l,int r){for(int i=l;i<=r;i++) Out_Couple(i);} inline void Out_M3(int l,int r){for(int i=l;i<=r;i++) Out_Three(i);} inline void Out_Rocket(){printf("Ww");} inline void Out_4Single(int x,int l,int r){Out_Boom(x); Out_Single(l); Out_Single(r);} inline void Out_4Couple(int x,int l,int r){Out_Boom(x); Out_Couple(l); Out_Couple(r);} inline bool Is_Empty(string s){return s.length()==&&s[]=='*';} inline bool Is_Single(string s){return s.length()==;} inline bool Is_Rocket(string s){return s=="Ww"||s=="wW";} inline bool Is_Couple(string s){return s.length()==&&s[]==s[];} inline bool Is_Three(string s){return s.length()==&&s[]==s[]&&s[]==s[];} inline bool Is_Boom(string s){return s.length()==&&s[]==s[]&&s[]==s[]&&s[]==s[];} inline bool Is_3Single(string s){return s.length()==&&s[]==s[]&&s[]==s[]&&s[]!=s[];} inline bool Is_3Couple(string s){return s.length()==&&s[]==s[]&&s[]==s[]&&s[]!=s[]&&s[]==s[];} inline bool Is_MS(string s){
int len=s.length(); if(len<) return ;
for(int i=;i<len;i++) if(GetVal(s[i-])+!=GetVal(s[i])) return ;
return ;
} inline bool Is_MC(string s){
int len=s.length(); if((len&)||len<) return ;
for(int i=;i<len;i+=){
if(s[i]!=s[i-]) return ;
}
for(int i=;i<len;i+=){
if(GetVal(s[i-])+!=GetVal(s[i])) return ;
}
return ;
} inline bool Is_4Single(string s){return s.length()==&&s[]==s[]&&s[]==s[]&&s[]==s[]&&s[]!=s[];} inline bool Is_4Couple(string s){return s.length()==&&s[]==s[]&&s[]==s[]&&s[]==s[]&&s[]!=s[]&&s[]==s[]&&s[]==s[];}

Helper.cpp

 /*
该部分函数用于判定是否可以出该类型的牌
以及
模拟出牌过程
*/ #include<bits/stdc++.h>
using namespace std; int GetVal(char c){
if(c=='T') return ;
if(c=='J') return ;
if(c=='Q') return ;
if(c=='K') return ;
if(c=='A') return ;
if(c=='') return ;
if(c=='w') return ;
if(c=='W') return ;
if(''<=c&&c<='') return c-'';
assert();
}
char SetChar(int x){
if(x<=) return ''+x;
if(x==) return 'T';
if(x==) return 'J';
if(x==) return 'Q';
if(x==) return 'K';
if(x==) return 'A';
if(x==) return '';
if(x==) return 'w';
if(x==) return 'W';
assert();
} struct player{
int a[];
player(){memset(a,,sizeof(a));}
void read(){//Input Poker
memset(a,,sizeof(a));
string s; cin>>s; int len=s.length();
for(int i=;i<len;i++)
a[GetVal(s[i])]++;
} void out(){//Output Poker
for(int i=;i<;i++)
for(int j=;j<a[i];j++)
putchar(SetChar(i));
putchar('\n');
} inline bool CanPlaySingle(int x){return a[x]>=;}//单 inline bool CanPlayCouple(int x){return a[x]>=;}//对 inline bool CanPlayThree(int x){return a[x]>=;}//三张 inline bool CanPlayBoom(int x){return a[x]>=;}//炸弹 inline bool CanPlayRocket(){return a[]&&a[];}//火箭 inline bool CanPlayMoreSingle(int l,int r){//顺子
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlaySingle(i)) return ;
return ;
} inline bool CanPlayMoreCouple(int l,int r){//连对
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayCouple(i)) return ;
return ;
} inline bool CanPlayMoreThree(int l,int r){//飞机
if(r-l+<||r>=) return ;
for(int i=l;i<=r;i++) if(!CanPlayThree(i)) return ;
return ;
} inline bool CanPlay4Single(int x,int l,int r){//四带二
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayCouple(l);
return CanPlayBoom(x)&&CanPlaySingle(l)&&CanPlaySingle(r);
} inline bool CanPlay4Couple(int x,int l,int r){//四带对
if(x==l||x==r) return ;
if(l==r) return CanPlayBoom(x)&&CanPlayBoom(l);
return CanPlayBoom(x)&&CanPlayCouple(l)&&CanPlayCouple(r);
} inline bool CanPlay3Single(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlaySingle(y);
} inline bool CanPlay3Couple(int x,int y){
if(x==y) return ;
return CanPlayThree(x)&&CanPlayCouple(y);
} inline void PlaySingle(int x){a[x]--;} inline void PlayCouple(int x){a[x]-=;} inline void PlayThree(int x){a[x]-=;} inline void PlayBoom(int x){a[x]-=;} inline void PlayRocket(){a[]--;a[]--;} inline void PlayMoreSingle(int l,int r){for(int i=l;i<=r;i++) PlaySingle(i);} inline void PlayMoreCouple(int l,int r){for(int i=l;i<=r;i++) PlayCouple(i);} inline void PlayMoreThree(int l,int r){for(int i=l;i<=r;i++) PlayThree(i);} inline void Play4Single(int x,int l,int r){PlayBoom(x); PlaySingle(l); PlaySingle(r);} inline void Play4Couple(int x,int l,int r){PlayBoom(x); PlayCouple(l); PlayCouple(r);} inline void Play3Single(int x,int y){PlayThree(x); PlaySingle(y);} inline void Play3Couple(int x,int y){PlayThree(x); PlayCouple(y);} inline bool empty(){
for(int i=;i<;i++)
if(a[i])
return ;
return ;}//判断是否出完 inline long long Hash(){long long res=; for(int i=;i<;i++) res=res<<|a[i]; return res;}//哈希值 inline int GetMin(){for(int i=;i<;i++) if(a[i]) return i; assert();}
inline int GetMax(){for(int i=;~i;i--) if(a[i]) return i; return -;}
};

Player.cpp

主代码:

 #include "Player.cpp"
#include "Helper.cpp" #define END {if(fir){newA=a; newB=b;} return 1;}
#define NXT {if(ok&&play(b,a,0)==0) return 1; else return 0;}
#define NO {printf("Can't Out\n"); newA=a; newB=b;}
player newA,newB;
bool play(player,player,bool); bool Play_Rocket(player a,player b,bool fir){
if(b.empty()) return ;
if(a.CanPlayRocket()){
a.PlayRocket();
bool now=play(a,b,);
if(now){
if(fir) Out_Rocket();
END;
}
}
return ;
} bool Play_Boom(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
if(Play_Rocket(a,b,fir)) return ;
player _a=a;
for(int i=last+;i<;i++)
if(a.CanPlayBoom(i)){
a.PlayBoom(i);
bool now=Play_Boom(b,a,i,,);
if(!now){
if(fir) Out_Boom(i);
END;
}
a=_a;
}
NXT;
} bool Play_Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlaySingle(i)){
a.PlaySingle(i);
bool now=Play_Single(b,a,i,,);
if(!now){
if(fir) Out_Single(i);
END;
}
a=_a;
}
NXT;
} bool Play_Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlayCouple(i)){
a.PlayCouple(i);
bool now=Play_Couple(b,a,i,,);
if(!now){
if(fir) Out_Couple(i);
END;
}
a=_a;
}
NXT;
} bool Play_Three(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++)
if(a.CanPlayThree(i)){
a.PlayThree(i);
bool now=Play_Three(b,a,i,,);
if(!now){
if(fir) Out_Three(i);
END;
}
a=_a;
}
NXT;
} bool Play_3Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
for(int j=;j<;j++)
if(a.CanPlay3Single(i,j)){
a.Play3Single(i,j);
bool now=Play_3Single(b,a,i,,);
if(!now){
if(fir) Out_3Single(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_3Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayThree(i))
for(int j=;j<;j++)
if(a.CanPlay3Couple(i,j)){
a.Play3Couple(i,j);
bool now=Play_3Couple(b,a,i,,);
if(!now){
if(fir) Out_3Couple(i,j);
END;
}
a=_a;
}
NXT;
} bool Play_4Single(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Single(i,j,k)){
a.Play4Single(i,j,k);
bool now=Play_4Single(b,a,i,,);
if(!now){
if(fir) Out_4Single(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_4Couple(player a,player b,int last,bool fir,bool ok){
if(b.empty()) return ;
player _a=a;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=last+;i<;i++) if(a.CanPlayBoom(i))
for(int j=;j<;j++)
for(int k=;k<;k++)
if(a.CanPlay4Couple(i,j,k)){
a.Play4Couple(i,j,k);
bool now=Play_4Couple(b,a,i,,);
if(!now){
if(fir) Out_4Couple(i,j,k);
END;
}
a=_a;
}
NXT;
} bool Play_MS(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreSingle(i,i+pls)){
a.PlayMoreSingle(i,i+pls);
bool now=Play_MS(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MS(i,i+pls);
END;
}
a=_a;
}
NXT;
} bool Play_MC(player a,player b,int l,int r,bool fir,bool ok){
if(b.empty()) return ;
player _a=a; int pls=r-l;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=l+;i+pls<=;i++)
if(a.CanPlayMoreCouple(i,i+pls)){
a.PlayMoreCouple(i,i+pls);
bool now=Play_MC(b,a,i,i+pls,,);
if(!now){
if(fir) Out_MC(i,i+pls);
END;
}
a=_a;
}
NXT;
} bool play(player a,player b,bool fir=){
if(b.empty()) return ;
if(Play_Boom(a,b,-,fir,)) return ;
for(int i=;i>=;i--){
if(Play_MS(a,b,-,-+i,fir,)) return ;
}
for(int i=;i>=;i--){
if(Play_MC(a,b,-,-+i,fir,)) return ;
}
if(Play_Three(a,b,-,fir,)) return ;
if(Play_3Single(a,b,-,fir,)) return ;
if(Play_3Couple(a,b,-,fir,)) return ;
if(Play_Couple(a,b,-,fir,)) return ;
if(Play_Single(a,b,-,fir,)) return ;
if(Play_4Single(a,b,-,fir,)) return ;
if(Play_4Couple(a,b,-,fir,)) return ;
return ;
} int Main(){
player a,b;
printf("INPUT AI:\n");
b.read();
printf("INPUT PLAYER:\n");
a.read();
if(!play(a,b,)){
printf("DIE\n");
return ;
}
while(){
a=newA; b=newB;
printf("\n");
if(a.empty()){
printf("WIN\n");
return ;
} string now; cin>>now;
if(now=="EXIT") return ;
if(Is_Empty(now)){
if(!play(a,b,)){
printf("DIE\n");
}
continue;
}
for(int i=;i<now.length();i++) b.PlaySingle(GetVal(now[i])); if(Is_Single(now)&&Play_Single(a,b,GetVal(now[]),,)==) NO;
if(Is_Couple(now)&&Play_Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_Three(now)&&Play_Three(a,b,GetVal(now[]),,)==) NO;
if(Is_Boom(now)&&Play_Boom(a,b,GetVal(now[]),,)==) NO;
if(Is_Rocket(now)&&Play_Rocket(a,b,)==) NO;
if(Is_3Single(now)&&Play_3Single(a,b,GetVal(now[]),,)==) NO;
if(Is_3Couple(now)&&Play_3Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_4Single(now)&&Play_4Single(a,b,GetVal(now[]),,)==) NO;
if(Is_4Couple(now)&&Play_4Couple(a,b,GetVal(now[]),,)==) NO;
if(Is_MS(now)&&Play_MS(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
if(Is_MC(now)&&Play_MC(a,b,GetVal(now[]),GetVal(now[now.length()-]),,)==) NO;
}
} int main(){
while() Main();
}

基于Alpha-Beta剪枝的欢乐斗地主残局辅助的更多相关文章

  1. 扩增子分析解读6进化树 Alpha Beta多样性

    分析前准备 # 进入工作目录 cd example_PE250 上一节回顾:我们的OTU获得了物种注释,并学习OTU表的各种操作————添加信息,格式转换,筛选信息.   接下来我们学习对OTU序列的 ...

  2. (转)unity中基于alpha通道的shadow volume实现

    转自:http://blog.163.com/wmk_2000_ren/blog/static/138846192201019114117466/ 实现呢,Aras大神已经给出了, http://fo ...

  3. 《QQ欢乐斗地主》山寨版

    使用Cocos2d-x编写,模仿<QQ欢乐斗地主>的界面实现了一个具有简单AI的单机版斗地主游戏. 游戏的详细说明请查看游戏目录下的help.txt文件. 下载地址: http://dow ...

  4. 软件发布版本区别介绍-Alpha,Beta,RC,Release

    Alpha: Alpha是内部测试版,一般不向外部发布,会有很多Bug.除非你也是测试人员,否则不建议使用. 是希腊字母的第一位,表示最初级的版本 alpha就是α,beta就是β alpha版就是比 ...

  5. 软工+C(2017第4期) Alpha/Beta换人

    // 上一篇:超链接 // 下一篇:工具和结构化 注:在一次软件工程讨论课程进度设计的过程中,出现了这个关于 Alpha/Beta换人机制的讨论,这个机制在不同学校有不同的实施,本篇积累各方观点,持续 ...

  6. 软工+C(4): Alpha/Beta换人

    // 上一篇:超链接 // 下一篇:工具和结构化 注:在一次软件工程讨论课程进度设计的过程中,出现了这个关于 Alpha/Beta换人机制的讨论,这个机制在不同学校有不同的实施,本篇积累各方观点,持续 ...

  7. K 班1-7,alpha,beta 作业成绩汇总

    K 班1-7,alpha,beta 作业成绩汇总 千帆竞发 详细得分 短学号 名 1 2 3 4 5 6 7 alpha beta TOTAL 505 基智 4.55 1 -2 0 0 -10 4.3 ...

  8. 九度oj 题目1363:欢乐斗地主

    题目描述: 如果大家玩过欢乐斗地主这个游戏,就一定知道有一个具有“提示”功能的按钮.如果你不知道你现在手里的牌有没有比上家大的牌,并且你也懒得去一张一张地看你手中的牌.这时候你就可以点“提示”按钮,系 ...

  9. 软件版本GA,RC,alpha,beta含义

    软件版本GA,RC,alpha,beta含义 (1)RC:(Release Candidate) Candidate是候选人的意思,用在软件上就是候选版本.Release.Candidate.就是发行 ...

随机推荐

  1. 使用svn进行文件和文件夹的忽略

    使用svn进行文件和文件夹的忽略 黑泥卡 关注  0.3 2016.08.16 22:42* 字数 786 阅读 20554评论 7喜欢 15 如何使用svn忽略文件和文件夹如果你之前尝试过git,你 ...

  2. JS require and import

    作者:寸志链接:https://www.zhihu.com/question/56820346/answer/150724784来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  3. laravel-debugbar安装

    第一步:找到debugbar扩展包 扩展包的链接:https://packagist.org/packages/barryvdh/laravel-debugbar 第二步:安装 我测试的环境larav ...

  4. 4-3 重构发送post请求

    当创建好一个post请求后 怎么测试呢?

  5. Mysql 导入导出表结构与数据

    1.导出整个数据库 mysqldump -u用户名 -p密码  数据库名 > 导出的文件名  C:\Users\jack> mysqldump -uroot -pmysql account ...

  6. 数组,arrayList和List

    数组,arrayList和List (1)数组在C#中是最早出现的.它在内存中是连续的存储的,所以索引速度很快,而且赋值与修改元素也很简单.可以利用偏移地址访问元素,时间复杂度为O(1);可以用折半查 ...

  7. angular 实现 echarts 拖动区域进行放大 方法

    实现逻辑: 1.通过鼠标摁下事件  和弹出事件  获取x轴的index  之后去x轴的list中去获取两个坐标点 2.之后将这两个数据作为参数  传到后台更新数据 3.记录下来这两个坐标点 放到lis ...

  8. [转]BSD系统正在死亡?一些安全研究人员这样认为

    摘要:在代码安全上被关注太少,漏洞没有被报告修补,FreeBSD.OpenBSD和NetBSD还能活下来吗? 在德国莱比齐的34c3网站上,IOActive的渗透测试主管Ilja von Sprund ...

  9. Redis sentinel之集群搭建

    环境 由于不太熟悉docker,所以,把docker当虚拟机来用,服务器环境如下: Redis Server 环境搭建 Redis Server 01 搭建 并且制作Redis镜像 容器建立 # do ...

  10. [译]迁移到新的 React Context Api

    随着 React 16.3.0 的发布,context api 也有了很大的更新.我已经从旧版的 api 更新到了新版.这里就分享一下我(作者)的心得体会. 回顾 下面是一个展示如何使用旧版 api ...