做完 pkusc2022 day2t3 雀圣之后跑来做这题。
首先我们考虑雀圣那题。那个题是说给你一副 13 张的手牌,让你算向听数。设 dp[i][j][0/1][p1][p2][up][dn]=0/1 表示考虑到 i 花色第 j 张牌,是否已经有雀头,上张牌剩下 p1 张,这张牌剩下 p2 张,已经加了 up 张,已经扔了 dn 张的状态是否可以达到。枚举当前这张牌加几张、删几张,是否作为雀头,能作为刻子就一定作为刻子,和前两张牌组成顺子,然后转移一下。每一种花色转移完之后清掉除 p1=p2=0 之外的所有状态即可。
有了这个 dp 这题剩下的就不难了。特殊牌的话就先处理一下,PASS
就多跳一个,DOUBLE
和 REVERSE
就定义一个 delta=1/−1,每次加 delta 表示顺/逆时针即可。进入打牌阶段之后,对每个玩家记一个当前和牌距离。打牌就是每次枚举打哪一张,dp算一下取一个和牌距离最短且最大的,打出去之后再对另外的玩家判一下碰和吃即可。虽然复杂度比较高,但是看起来可以过。
code(8.3k):
点击查看代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#define memset __builtin_memset
#define mp std::make_pair
#define fi first
#define se second
typedef std::pair<int,int> pii;
std::map<char,int> ms;
inline void chkmin(int &a,const int &b){if(b<a)a=b;}
inline char cc(int x){return (char)(x+'A');}
inline char cn(int x){return (char)(x+'0');}
char nam[8]={'0','E','S','W','N','B','F','Z'},nam1[3]={'M','P','S'};
int limt[5]={9,9,9,7,3};
std::string nam2[4]={"","PASS","REVERSE","DOUBLE"};
inline void init(){
ms['E']=1,ms['S']=2,ms['W']=3,ms['N']=4,ms['B']=5,ms['F']=6,ms['Z']=7;
}
inline std::string f(pii x){
std::string res="";
if(x.fi<=2) res+=cn(x.se),res+=nam1[x.fi];
else if(x.fi==3) res+=nam[x.se];
else res=nam2[x.se];
return res;
}
int a[4][5][10],to[4];
inline void print_in(int o,const char *in){printf("%c IN %s\n",cc(o),in);}
inline void print_out(int o,const char *out,int oo){
if(out[0]=='P') printf("%c OUT %s %c\n",cc(o),out,cc(oo));
else printf("%c OUT %s\n",cc(o),out);
}
inline void print_pong(int o,const char *pong){printf("%c PONG %s %s %s\n",cc(o),pong,pong,pong);}
inline void print_chow(int o,const char *chow1,const char *chow2,const char *chow3){printf("%c CHOW %s %s %s\n",cc(o),chow1,chow2,chow3);}
inline void print_selfdrawn(int o){printf("%c SELFDRAWN\n",cc(o));}
inline void print_ron(int o){printf("%c RON\n",cc(o));}
inline void print_win(int o){printf("%c WIN\n",cc(o));}
inline void rd(int o,const char *in){
if(in[0]=='P') a[o][4][1]++;
else if(in[0]=='R') a[o][4][2]++;
else if(in[0]=='D') a[o][4][3]++;
else if(in[0]>='1'&&in[0]<='9'){
int tmp;
if(in[1]=='M') tmp=0;else if(in[1]=='P') tmp=1;else tmp=2;
a[o][tmp][in[0]-'0']++;
}
else a[o][3][ms[in[0]]]++;
}
inline int findans(int a[5][10],bool flag=0){
static bool dp[6][10][2][3][3][14][13];
memset(dp,0,sizeof dp);
dp[0][0][0][0][0][0][0]=1;
for(int o=0;o<=4;++o){
for(int i=1;i<=limt[o];++i){
for(int qt=0;qt<=1;++qt)
for(int p1=0;p1<=2;++p1)
for(int p2=p1;p2<=2;++p2)
for(int up=0;up<=13;++up)
for(int dn=0;dn<=12;++dn){
if(!dp[o][i-1][qt][p1][p2][up][dn]) continue;
//不加不减
int now=a[o][i];
//雀头
if(o<=3&&!qt&&now>=2){
now-=2;
if(!p1) dp[o][i][1][p2][now][up][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][1][p2-1][now-1][up][dn]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][1][p2-2][now-2][up][dn]=1;
now+=2;
}
//是否有刻子
if(o<=3&&now>=3){
now-=3;
if(!p1) dp[o][i][qt][p2][now][up][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up][dn]=1;
}
else{
if(!p1) dp[o][i][qt][p2][now][up][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up][dn]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][qt][p2-2][now-2][up][dn]=1;
}
for(int j=1;j<=4-a[o][i]&&up+j<=13;++j){//加
now=a[o][i]+j;
if(o<=3&&!qt&&now>=2){
now-=2;
if(!p1) dp[o][i][1][p2][now][up+j][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][1][p2-1][now-1][up+j][dn]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][1][p2-2][now-2][up+j][dn]=1;
now+=2;
}
if(o<=3&&now>=3){
now-=3;
if(!p1) dp[o][i][qt][p2][now][up+j][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up+j][dn]=1;
}
else{
if(!p1) dp[o][i][qt][p2][now][up+j][dn]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up+j][dn]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][qt][p2-2][now-2][up+j][dn]=1;
}
}
for(int j=1;j<=a[o][i]&&dn+j<=12;++j){//减
now=a[o][i]-j;
if(o<=3&&!qt&&now>=2){
now-=2;
if(!p1) dp[o][i][1][p2][now][up][dn+j]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][1][p2-1][now-1][up][dn+j]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][1][p2-2][now-2][up][dn+j]=1;
now+=2;
}
if(o<=3&&now>=3){
now-=3;
if(!p1) dp[o][i][qt][p2][now][up][dn+j]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up][dn+j]=1;
}
else{
if(!p1) dp[o][i][qt][p2][now][up][dn+j]=1;
if(o<=2&&p1==1&&p2>=1&&now>=1) dp[o][i][qt][p2-1][now-1][up][dn+j]=1;
if(o<=2&&p1==2&&p2>=2&&now>=2) dp[o][i][qt][p2-2][now-2][up][dn+j]=1;
}
}
}
}
for(int qt=0;qt<=1;++qt)
for(int up=0;up<=13;++up)
for(int dn=0;dn<=12;++dn)
dp[o+1][0][qt][0][0][up][dn]=dp[o][limt[o]][qt][0][0][up][dn];
}
for(int ans=0;ans<=12;++ans)
if(dp[5][0][1][0][0][ans+flag][ans]) return ans+flag;
}
inline pii findout(int o){
for(int i=1;i<=3;++i)
if(a[o][4][i]) return --a[o][4][i],mp(4,i);
int res=13;pii ans;
for(int oo=3;oo>=0;--oo)
for(int i=limt[oo];i;--i){
if(!a[o][oo][i]) continue;
a[o][oo][i]--;int tmp;
if((tmp=findans(a[o],1))<res) res=tmp,ans=mp(oo,i);
a[o][oo][i]++;
}
return --a[o][ans.fi][ans.se],to[o]=res,ans;
}
inline bool drawn(int a[5][10]){
if(a[4][1]||a[4][2]||a[4][3]) return 0;
int b[5][10];
for(int oo=0;oo<=3;++oo)
for(int ii=1;ii<=limt[oo];++ii){
for(int ooo=0;ooo<=3;++ooo)for(int iii=1;iii<=limt[ooo];++iii)b[ooo][iii]=a[ooo][iii];
if(b[oo][ii]<2) continue;
b[oo][ii]-=2;bool ok=1;
for(int o=0;o<=3;++o){
for(int i=1;i<=limt[o];++i){
if(b[o][i]>=3) b[o][i]-=3;
if(o==3&&b[o][i]){ok=0;break;}
while(b[o][i]){
if(i>7||!b[o][i+1]||!b[o][i+2]){ok=0;break;}
--b[o][i],--b[o][i+1],--b[o][i+2];
}
if(!ok) break;
}
if(!ok) break;
}
if(ok) return 1;
}
return 0;
}
inline bool ron(int o,pii x){
a[o][x.fi][x.se]++;
bool ans=drawn(a[o]);
a[o][x.fi][x.se]--;
return ans;
}
inline bool pong(int o,pii x){
if(a[o][x.fi][x.se]<2) return 0;
a[o][x.fi][x.se]-=2;
int now=findans(a[o]);
if(now<to[o]) return to[o]=now,1;
return a[o][x.fi][x.se]+=2,0;
}
inline int chow(int o,pii x){
if(x.se<=7&&a[o][x.fi][x.se+1]&&a[o][x.fi][x.se+2]){
a[o][x.fi][x.se+1]--,a[o][x.fi][x.se+2]--;
int now=findans(a[o]);
if(now<to[o]) return to[o]=now,1;
a[o][x.fi][x.se+1]++,a[o][x.fi][x.se+2]++;
}
if(x.se<=8&&x.se>=2&&a[o][x.fi][x.se-1]&&a[o][x.fi][x.se+1]){
a[o][x.fi][x.se-1]--,a[o][x.fi][x.se+1]--;
int now=findans(a[o]);
if(now<to[o]) return to[o]=now,2;
a[o][x.fi][x.se-1]++,a[o][x.fi][x.se+1]++;
}
if(x.se>=3&&a[o][x.fi][x.se-2]&&a[o][x.fi][x.se-1]){
a[o][x.fi][x.se-2]--,a[o][x.fi][x.se-1]--;
int now=findans(a[o]);
if(now<to[o]) return to[o]=now,3;
a[o][x.fi][x.se-2]++,a[o][x.fi][x.se-1]++;
}
return 0;
}
int main(){
// freopen("a.in","r",stdin);freopen("a.out","w",stdout);
// return system("fc P7147_2.out data.out"),0;
#ifdef LOCAL
freopen("29.in","r",stdin);
// freopen("a.out","w",stdout);
#endif
init();
int o=0,delta=1,Cnt=52;
while(Cnt--){
char in[10];scanf("%s",in);
print_in(o,in);rd(o,in);
o=(o+delta+4)%4;
}
for(int pp=0;pp<=3;++pp){
int res=13;
for(int oo=0;oo<=3;++oo)
for(int i=1;i<=limt[oo];++i)
++a[pp][oo][i],chkmin(res,findans(a[pp])+1),--a[pp][oo][i];
to[pp]=res;
}
Cnt=96;bool flag=0;int win=-1;
while(Cnt--){
int ff=1;char in[10];
if(!flag){
scanf("%s",in);
print_in(o,in);rd(o,in);
}
else ++Cnt,flag=0;
if(drawn(a[o])){print_selfdrawn(o),win=o;break;}
pii res=findout(o);
print_out(o,f(res).c_str(),(o+delta*ff+4)%4);
if(res.fi==4){
if(res.se==2) delta*=-1;
else if(res.se==3) ff=0;
else o=(o+delta*ff+4)%4;
o=(o+delta*ff+4)%4;
continue;
}
if(res.fi<=3){
for(int nn=(o+delta+4)%4;nn!=o;nn=(nn+delta+4)%4)
if(ron(nn,res)){print_ron(nn),win=nn;break;}
if(win!=-1) break;
bool jump=0;
for(int nn=0;nn<=3;++nn)
if(nn!=o&&pong(nn,res)){print_pong(nn,f(res).c_str()),o=nn,flag=1,jump=1;break;}
if(jump) continue;
}
if(res.fi<=2){
int tmp;
if(tmp=chow((o+delta+4)%4,res)){
o=(o+delta+4)%4,flag=1;
if(tmp==1) print_chow(o,f(mp(res.fi,res.se)).c_str(),f(mp(res.fi,res.se+1)).c_str(),f(mp(res.fi,res.se+2)).c_str());
else if(tmp==2) print_chow(o,f(mp(res.fi,res.se-1)).c_str(),f(mp(res.fi,res.se)).c_str(),f(mp(res.fi,res.se+1)).c_str());
else print_chow(o,f(mp(res.fi,res.se-2)).c_str(),f(mp(res.fi,res.se-1)).c_str(),f(mp(res.fi,res.se)).c_str());
continue;
}
}
o=(o+delta*ff+4)%4;
}
if(win==-1) puts("DRAW");
else print_win(win);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 因为Apifox不支持离线,我果断选择了Apipost!
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端