一个简化版的回合制游戏(万智牌?)的游戏规则,要求你模拟出游戏结果。
官方题解:硬核模拟,写就行了。。。 (比赛时真没法写)
题目不难读,就是容易漏细节,写了2h+debug了2h+wa了1h才过。也没什么办法,以后读题要仔细,读完写的时候别把细节忘了,最好列出来。
这次用了一大堆STL压进两百行,而且写的还算清晰,按照几年前的码风估计得到400行。
/*
Author: fffasttime
Date: 2019/07/21 15:00
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inc(i,n) for (int i=0;i<n;i++)
#define DR(X) int X; scanf("%d",&X);
const int N=100010;
int c[2][4][5];//deck,hand,field,grave //plain, swamp, mountain, island, forest
vector<int> deck[2];
int opt[4][5]{
{2,1,3,5,4},
{3,4,2,1,5},
{4,5,3,2,1},
{5,2,3,4,1}};
template <int tp>
bool cmp(int x, int y){return opt[tp][x]<opt[tp][y];}
int turn,step;
void mv(int tr, int fr, int to, int d){
//printf("player %d: %d , %d-->%d\n",tr, d, fr, to);
assert(c[tr][fr][d]>0);
c[tr][fr][d]--;
c[tr][to][d]++;
}
void draw(int tr=turn){
if (deck[tr].empty()) return;
//printf("(draw) ");
int d=deck[tr].back();
deck[tr].pop_back();
mv(tr,0,1,d);
}
void discard(int tr){
int ocr=0;
int sel[5],sc=0;
inc(i,5) if (c[tr][1][i]){
if (c[tr][1][i]>ocr){
sc=0; ocr=c[tr][1][i];
sel[sc++]=i;
}
else if (c[tr][1][i]==ocr){
sel[sc++]=i;
}
}
assert(sc);
sort(sel,sel+sc,cmp<1>);
//printf("(discard) ");
mv(tr,1,3,sel[0]);
}
void destroy(int tr){
int ocr=100;
int sel[5],sc=0;
inc(i,5) if (c[tr][2][i]){
if (c[tr][2][i]<ocr){
sc=0; ocr=c[tr][2][i];
sel[sc++]=i;
}
else if (c[tr][2][i]==ocr){
sel[sc++]=i;
}
}
assert(sc);
sort(sel,sel+sc,cmp<2>);
//printf("(destroy) ");
mv(tr,2,3,sel[0]);
}
void recycle(int tr){
int ocr=100;
int sel[5],sc=0;
inc(i,5) if (c[tr][3][i]){
if (c[tr][2][i]+c[tr][1][i]<ocr){
sc=0; ocr=c[tr][2][i]+c[tr][1][i];
sel[sc++]=i;
}
else if (c[tr][2][i]+c[tr][1][i]==ocr){
sel[sc++]=i;
}
}
assert(sc);
sort(sel,sel+sc,cmp<3>);
//printf("(recycle) ");
mv(tr,3,1,sel[0]);
}
void eff(int d){ //type
switch(d){
case 0: draw(); break;
case 1: discard(!turn); break;
case 2: destroy(!turn); break;
case 4: recycle(turn); break;
}
}
bool cheff(int d){
switch(d){
case 0: return deck[turn].size();
case 1: {
inc(i,5) if (c[!turn][1][i]) return 1;
return 0;
}
case 2:{
inc(i,5) if (c[!turn][2][i]) return 1;
return 0;
}
case 4:{
inc(i,5) if (c[turn][3][i]) return 1;
return 0;
}
}
return 0; //island
}
bool counter(int d){
if (c[!turn][1][3]<1 || accumulate(c[!turn][1],c[!turn][1]+5,0)<2) return 0;
if (count_if(c[turn][2],c[turn][2]+5,[](int x){return x;})<4) return 0;
for (int i=0;i<5;i++) if (c[turn][2][i]==0 && c[turn][3][i]>=5) return 0;
mv(turn,1,3,d);
mv(!turn,1,3,3); //counter
discard(!turn);
return 1;
}
void play(){
int p[5]; //play type
int pri=0,pc=0;
inc(i,5) if (c[turn][1][i]){
int np;
if (c[turn][2][i]) np=1;
else{
if (cheff(i)) np=3;
else np=2;
}
if (np>pri){
pc=0; pri=np;
p[pc++]=i;
}
else if (np==pri){
p[pc++]=i;
}
}
if (pri<2) return;
if (pc>1)
sort(p,p+pc,cmp<0>);
int cur=p[0];
if (counter(cur)){
return;
}
//printf("(play) ");
mv(turn,1,2,cur);
if (pri==3) eff(cur);
}
void solve(){
memset(c,0,sizeof c);
deck[0].clear(); deck[1].clear();
inc(i,25) {DR(t) c[0][0][t]++; deck[0].push_back(t);}
inc(i,25) {DR(t) c[1][0][t]++; deck[1].push_back(t);}
turn=0,step=1;
reverse(deck[0].begin(), deck[0].end());
reverse(deck[1].begin(), deck[1].end());
inc(i,5) draw(0);
inc(i,5) draw(1);
while (1){
draw();
play();
if (step>=100 || all_of(c[turn][2],c[turn][2]+5, [](int x){return x;}))
break;
if (none_of(c[turn][0],c[turn][0]+10,[](int x){return x;})
&&none_of(c[!turn][0],c[!turn][0]+10,[](int x){return x;}))
break;
turn=!turn;
//for (int j=0;j<4;j++,cout<<'\n') inc(i,5) printf("%d ",c[0][j][i]); //printf(";");
//for (int j=0;j<4;j++,cout<<'\n') inc(i,5) printf("%d ",c[1][j][i]); printf("%d",step);
step++;
//puts("---------");
}
if (all_of(c[turn][2],c[turn][2]+5, [](int x){return x;})){
printf("%s",step&1?"Alice":"Bob");
}
else printf("Draw");
printf(" %d\n", step);
}
int main(){
int T; cin>>T;
for (int i=1;i<=T;i++){
printf("Case %d: ",i);
solve();
}
return 0;
}