猪国杀爆肝录
so_find_skind
·
·
个人记录
建立 《猪国杀爆肝录》,开始爆肝(
基本代码:
```cpp
#include<bits/stdc++.h>
using namespace std;
int n,m;
string a[15];
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
for(int i=1;i<=m;i++)
cin>>pd[i];
return 0;
}
```
$2023$ 年 $9$ 月 $4$ 日 $21:00$:
由于时间原因停肝,已完成主猪的基本牌出牌方案(不一定对,之后可能改),并完善了一些变量。
```cpp
#include<bits/stdc++.h>
using namespace std;
int n,m,q=1,xue[15];//q表示当前牌堆已发至第几张牌,xue[]表示当前角色血量
string a[15],g[15];//g[]表示目前该角色标明的身份
bool dead[15];//该猪是否死亡
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
int check(){//判断是否结束且胜者的函数
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]=="FP" && !dead[i]){//该猪是反猪且没有死亡
flag=0;//则主猪、忠猪没有胜利
break;
}
if(flag)
return flag;//已结束且主猪、忠猪胜利了
if(dead[1])
return 2;//主猪死亡,反猪胜利
return 0;
}
void kouxue(int idx){
xue[idx]--;
if(xue[idx]==0){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='P'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
xue[idx]++;
return ;
}
}
dead[idx]=true;
}
}
void shan(int idx){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='D'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(idx);//扣血
}
void sha(int idx){
int f1=0,f2=0;
for(int i=2;i<=n;i++)
if(!dead[i]){
f1=i;
break;
}
for(int i=n;i>=2;i--)
if(!dead[i]){
f2=i;
break;
}
if(g[f1]=="LFP"){//是类反猪
while(!dead[f1] && pai[idx][l[idx]]=='K'){
l[idx]++;
shan(f1);
}
}
if(f1!=f2 && g[f2]=="LFP"){//是类反猪,注意不能重合
while(!dead[f2] && pai[idx][l[idx]]=='K'){
l[idx]++;
shan(f1);
}
}
}
int main(){
cin>>n>>m;
g[1]="MP";
for(int i=1;i<=n;i++){
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
l[i]=1;//左端点置为1
r[i]=4;//右端点置为4
xue[i]=4;
}
for(int i=1;i<=m;i++)
cin>>pd[i];
while(!check()){
for(int i=1;i<=n;i++){
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(q!=m)
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(a[i]=="MP"){
while(true){
if(pai[i][l[i]]=='P')
if(xue[i]!=4){
xue[i]++;
l[i]++;
}else
break;
else if(pai[i][l[i]]=='D')
break;
else if(pai[i][l[i]]=='K')
sha(i);
}
}
}
}
return 0;
}
```
$2023$ 年 $9$ 月 $5$ 日 $13:33$:
成功写出了万箭齐发、南猪入侵及主猪视角下的杀、决斗,暂时没考虑无懈可击的情况并再次完善变量。
```cpp
#include<bits/stdc++.h>
using namespace std;
int wuqi[15];//可出杀的数量
int n,m,q=1,xue[15];//q表示当前牌堆已发至第几张牌,xue[]表示当前角色血量
string a[15],g[15];//g[]表示目前该角色标明的身份
bool dead[15];//该猪是否死亡
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
int check(){//判断是否结束且胜者的函数
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]=="FP" && !dead[i]){//该猪是反猪且没有死亡
flag=0;//则主猪、忠猪没有胜利
break;
}
if(flag)
return flag;//已结束且主猪、忠猪胜利了
if(dead[1])
return 2;//主猪死亡,反猪胜利
return 0;
}
void kouxue(int idx){
xue[idx]--;
if(xue[idx]==0){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='P'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
xue[idx]++;
return ;
}
}
dead[idx]=true;
}
}
void shan(int idx){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='D'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(idx);//扣血
}
void shaa(int idx){//同shan()
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='K'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(idx);//扣血
}
void sha(int idx){
int f1=0,f2=0;
for(int i=idx+1;i<=n;i++)
if(!dead[i]){
f1=i;
break;
}
if(!f1)
for(int i=1;i<idx;i++)
if(!dead[i]){
f1=i;
break;
}
for(int i=idx-1;i>=1;i--)
if(!dead[i]){
f2=i;
break;
}
for(int i=n;i>=idx+1;i--)
if(!dead[i]){
f1=i;
break;
}
if(a[idx]=="MP"){
if(g[f1]=="LFP"){//类反猪
while(!dead[f1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(f1);
}
}
if(f1!=f2 && g[f2]=="LFP"){//同上
while(!dead[f2] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//同上
l[idx]++;
shan(f2);
}
}
}
}
void duisha(int i,int j){//到i出杀
int q=xue[i];
shaa(i);//出一张杀
if(q==xue[i])
duisha(j,i);//对调,到j出杀
}
void juedou(int idx){
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx){
if(a[idx]=="MP" && g[i]=="LFP"){
while(pai[idx][l[idx]]=='F'){
duisha(i,idx);//开始决斗
l[idx]++;
}
}
}
}
}
void wanjianqifa(int idx){
while(pai[idx][l[idx]]=='W'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx)
shan(i);//出一张闪
}
}
}
void nanzhuruqin(int idx){
while(pai[idx][l[idx]]=='N'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx)
shaa(i);//出一张杀
}
}
}
int main(){
cin>>n>>m;
g[1]="MP";
for(int i=1;i<=n;i++){
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
l[i]=1;//左端点置为1
r[i]=4;//右端点置为4
xue[i]=4;
}
for(int i=1;i<=m;i++)
cin>>pd[i];
while(!check()){
for(int i=1;i<=n;i++){
if(wuqi[i]==0)//重置,注意这里不需重置有武器的情况
wuqi[i]=1;
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(q!=m)
pai[i][r[i]++]=pd[q++];//摸牌阶段
while(true){
if(pai[i][l[i]]=='P')
if(xue[i]!=4){
xue[i]++;
l[i]++;
}else
break;
else if(pai[i][l[i]]=='D')
break;
else if(pai[i][l[i]]=='K' && wuqi[i]>0)
sha(i);
else if(pai[i][l[i]]=='F')
juedou(i);
else if(pai[i][l[i]]=='W')
wanjianqifa(i);
else if(pai[i][l[i]]=='N')
nanzhuruqin(i);
else if(pai[i][l[i]]=='J')
break;
else if(pai[i][l[i]]=='Z')
wuqi[i]=142857;//相当于无限出杀
else//防止有一堆杀但是只能出一张的情况
break;
}
}
}
return 0;
}
```
$2023$ 年 $9$ 月 $6$ 日 $19:19$:
完成了忠猪角度下的杀,并完成一部分反猪角度下的杀,成功的模拟了杀死反猪和主猪杀死忠猪的情况,暂时未对决斗的【发起者为主猪,接收者为忠猪】做出模拟。
```cpp
#include<bits/stdc++.h>
using namespace std;
int wuqi[15];//可出杀的数量
int n,m,q=1,xue[15];//q表示当前牌堆已发至第几张牌,xue[]表示当前角色血量
string a[15],g[15];//g[]表示目前该角色标明的身份
bool dead[15];//该猪是否死亡
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
int check(){//判断是否结束且胜者的函数
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]=="FP" && !dead[i]){//该猪是反猪且没有死亡
flag=0;//则主猪、忠猪没有胜利
break;
}
if(flag)
return flag;//已结束且主猪、忠猪胜利了
if(dead[1])
return 2;//主猪死亡,反猪胜利
return 0;
}
void kouxue(int i,int idx){
xue[idx]--;
if(xue[idx]==0){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='P'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
xue[idx]++;
return ;
}
}
dead[idx]=true;
}
if(dead[idx]==true){
if(a[idx]=="FP"){//杀死反猪,摸三张牌
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
}
if(a[idx]=="ZP" && a[i]=="MP"){//主猪杀死了忠猪
l[i]=r[i]=1;
pai[i][l[i]]='1';//模拟清空所有牌
}
}
if(a[idx]=="MP" && g[i]!="ZP")
g[i]="LFP";
}
void shan(int i,int idx){
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='D'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void shaa(int i,int idx){//同shan()
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='K'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void sha(int idx){
int f1=0,f2=0;
for(int i=idx+1;i<=n;i++)
if(!dead[i]){
f1=i;
break;
}
if(!f1)
for(int i=1;i<idx;i++)
if(!dead[i]){
f1=i;
break;
}
for(int i=idx-1;i>=1;i--)
if(!dead[i]){
f2=i;
break;
}
for(int i=n;i>=idx+1;i--)
if(!dead[i]){
f1=i;
break;
}
if(a[idx]=="MP"){
if(g[f1]=="LFP" || g[f1]=="FP"){//类反猪或反猪
while(!dead[f1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,f1);
}
}
if(f1!=f2 && (g[f2]=="LFP" || g[f2]=="FP")){//同上
while(!dead[f2] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//同上
l[idx]++;
shan(idx,f2);
}
}
}
if(a[idx]=="ZP"){//同主猪
if(g[f1]=="LFP" || g[f1]=="FP"){//类反猪或反猪
while(!dead[f1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,f1);
}
}
if(f1!=f2 && (g[f2]=="LFP" || g[f2]=="FP")){//同上
while(!dead[f2] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//同上
l[idx]++;
shan(idx,f2);
}
}
}
if(a[idx]=="FP"){//先杀主猪,再杀忠猪
if(a[f1]=="MP"){//还没完,还有f2是忠猪的情况
while(!dead[f1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,f1);
}
}
if(a[f2]=="MP"){//还没完,还有f1是忠猪的情况
while(!dead[f2] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){
l[idx]++;
shan(idx,f2);
}
}
}
}
void duisha(int i,int j){//到i出杀
int q=xue[i];
shaa(j,i);//出一张杀
if(q==xue[i])
duisha(j,i);//对调,到j出杀
}
void juedou(int idx){
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx){
if(a[idx]=="MP" && g[i]=="LFP"){
while(pai[idx][l[idx]]=='F'){
duisha(i,idx);//开始决斗
l[idx]++;
}
}
}
}
}
void wanjianqifa(int idx){
while(pai[idx][l[idx]]=='W'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx)
shan(idx,i);//出一张闪
}
}
}
void nanzhuruqin(int idx){
while(pai[idx][l[idx]]=='N'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx)
shaa(idx,i);//出一张杀
}
}
}
int main(){
cin>>n>>m;
g[1]="MP";
for(int i=1;i<=n;i++){
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
l[i]=1;//左端点置为1
r[i]=4;//右端点置为4
xue[i]=4;
}
for(int i=1;i<=m;i++)
cin>>pd[i];
while(!check()){
for(int i=1;i<=n;i++){
if(wuqi[i]==0)//重置,注意这里不需重置有武器的情况
wuqi[i]=1;
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(q!=m)
pai[i][r[i]++]=pd[q++];//摸牌阶段
while(true){
if(pai[i][l[i]]=='P')
if(xue[i]!=4){
xue[i]++;
l[i]++;
}else
break;
else if(pai[i][l[i]]=='D')
break;
else if(pai[i][l[i]]=='K' && wuqi[i]>0)
sha(i);
else if(pai[i][l[i]]=='F')
juedou(i);
else if(pai[i][l[i]]=='W')
wanjianqifa(i);
else if(pai[i][l[i]]=='N')
nanzhuruqin(i);
else if(pai[i][l[i]]=='J')
break;
else if(pai[i][l[i]]=='Z')
wuqi[i]=142857;//相当于无限出杀
else//防止有一堆杀但是只能出一张的情况或手里没牌
break;
}
}
}
return 0;
}
```
$2023$ 年 $9$ 月 $7$ 日 $13:26$:
成功的做出献殷勤及相对的表敌意,基本全部完成,但是 CE 了,先把代码放在这里.
```cpp
/*
#include<bits/stdc++.h>
using namespace std;
int main(){
srand(time(NULL));
cout<<rand()%36+1<<"\n";
int k=5;
cout<<"做"<<rand()%k+1<<"题";
return 0;
}
*/
#include<bits/stdc++.h>
using namespace std;
int wuqi[15];//可出杀的数量
int n,m,q=1,xue[15];//q表示当前牌堆已发至第几张牌,xue[]表示当前角色血量
string a[15],g[15];//g[]表示目前该角色标明的身份
bool dead[15];//该猪是否死亡
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
bool wuxiekeji(int idx){//是否能出一张无懈可击
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='J'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
g[idx]=a[idx];//重点!表敌意和献殷勤实际上就是跳忠或跳反
return true;
}
}
return false;
}
bool biaodiyi(int idx){//献殷勤的猪是idx
for(int i=1;i<=n;i++){
if(g[idx]="FP" && a[i]=="ZP" || g[idx]=="ZP" && a[i]=="FP" || g[idx]=="FP" && a[i]=="MP" || a[idx]=="MP" && g[i]=="FP"){//注意这里不存在类反猪,因为类反猪在献殷勤是一定被主猪重新认识了
if(wuxiekeji(i)){
g[i]=a[i];//同wuxiekeji()里的这句
return true;
}
}
}
return false;//失败了
}//注意这里的表敌意单指抵消献殷勤
bool xianyinqin(int idx){//是否成功献殷勤
for(int i=1;i<=n;i++){
if((g[idx]="FP" && a[i]=="FP") || (g[idx]=="ZP" && a[i]=="ZP") || (g[idx]=="ZP" && a[i]=="MP") || (a[idx]=="MP" && g[i]=="ZP")){
bool q,p;
while(q=wuxiekeji(i) && b=biaodiyi(i)){//出了但是被挡下了
g[i]=a[i];//同wuxiekeji()里的这句
}
if(q && !p){//出了但是没被挡下
g[i]=a[i];//同上
return true;
}
}
}
return false;//献殷勤失败
}
int check(){//判断是否结束且目前胜者的函数
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]=="FP" && !dead[i]){//该猪是反猪且没有死亡
flag=0;//则主猪、忠猪没有胜利
break;
}
if(flag)
return flag;//已结束且主猪、忠猪胜利了
if(dead[1])
return 2;//主猪死亡,反猪胜利
return 0;
}
void kouxue(int i,int idx){//扣血函数,i为伤害来源
xue[idx]--;
if(xue[idx]==0){
for(int i=l[idx];i<=r[idx];i++){//是否能吃桃补救
if(pai[idx][i]=='P'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
xue[idx]++;//补救成功了
return ;
}
}
dead[idx]=true;//失败了,则该猪死亡
}
if(dead[idx]==true){
if(a[idx]=="FP"){//杀死反猪,摸三张牌
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
}
if(a[idx]=="ZP" && a[i]=="MP"){//主猪杀死了忠猪
l[i]=r[i]=1;
pai[i][l[i]]='1';//模拟清空所有牌
}
}
if(a[idx]=="MP" && g[i]!="ZP")//还没跳忠的猪攻击了主猪
g[i]="LFP";
}
void shan(int i,int idx){//出一张闪
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='D'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void shaa(int i,int idx){//同shan()
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='K'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void sha(int idx){
int F=0,qqq=0;
for(int i=2;i<=n;i++)//找离主猪最近的向左可以攻击到主猪的猪
if(!dead[i]){
qqq=i;
break;
}
for(int i=idx+1;i<=n;i++)
if(!dead[i]){
F=i;
break;
}
if(!F)
for(int i=1;i<idx;i++)
if(!dead[i]){
F=i;
break;
}
if(a[idx]=="MP"){
if(g[F]=="LFP" || g[F]=="FP"){//类反猪或反猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
}
}
if(a[idx]=="ZP"){//同主猪
if(g[F]=="LFP" || g[F]=="FP"){//类反猪或反猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
g[F]="ZP";//跳忠
}
}
if(a[idx]=="FP"){//杀忠猪或主猪
if(idx==qqq){//可以向左攻击到主猪
while(!dead[1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀主猪
l[idx]++;
shan(idx,1);
}
g[F]="FP";//跳反
return ;
}
if(a[F]=="MP" || a[F]=="ZP"){//忠猪或主猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
g[F]="FP";//跳反
}
}
}
void duisha(int i,int j){//到i出杀
if(a[i]=="ZP" && a[j]=="MP"){//若发起者为主猪且接受者为忠猪,则忠猪直接扣血
kouxue[i];
return ;
}
int q=xue[i];
shaa(j,i);//出一张杀
if(q==xue[i])
duisha(j,i);//对调,到j出杀
}
void juedou(int idx){
if(a[idx]=="FP"){//注意反猪需要单独拎出来
duisha(1,idx);//无条件攻击主猪
g[idx]="FP";//跳反
return ;
}
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx){
if(a[idx]=="MP" && (g[i]=="LFP" || g[i]=="FP")){//攻击反猪或类反猪
while(pai[idx][l[idx]]=='F' && !xianyinqin(i)){//没人给他献殷勤
duisha(i,idx);//开始决斗
l[idx]++;
}
break;//只对其表敌意
}
if(a[idx]=="ZP" && (g[i]=="LFP" || g[i]=="FP")){//同主猪
while(pai[idx][l[idx]]=='F' && !xianyinqin(i)){//同上
duisha(i,idx);//开始决斗
l[idx]++;
}
g[idx]="ZP";//跳忠
break;//只对其表敌意
}
}
}
}
void wanjianqifa(int idx){
while(pai[idx][l[idx]]=='W'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx && !xianyinqin(i))//没人给他献殷勤
shan(idx,i);//出一张闪
}
}
}
void nanzhuruqin(int idx){
while(pai[idx][l[idx]]=='N'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx && !xianyinqin(i))//没人给他献殷勤
shaa(idx,i);//出一张杀
}
}
}
int main(){
cin>>n>>m;
g[1]="MP";
for(int i=1;i<=n;i++){
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
l[i]=1;//左端点置为1
r[i]=4;//右端点置为4
xue[i]=4;
}
for(int i=1;i<=m;i++)
cin>>pd[i];
while(!check()){
for(int i=1;i<=n;i++){
if(wuqi[i]==0)//重置,注意这里不需重置有武器的情况
wuqi[i]=1;
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(q!=m)
pai[i][r[i]++]=pd[q++];//摸牌阶段
while(true){
if(pai[i][l[i]]=='P')
if(xue[i]!=4){
xue[i]++;
l[i]++;
}else
break;
else if(pai[i][l[i]]=='D')
break;
else if(pai[i][l[i]]=='K' && wuqi[i]>0)
sha(i);
else if(pai[i][l[i]]=='F')
juedou(i);
else if(pai[i][l[i]]=='W')
wanjianqifa(i);
else if(pai[i][l[i]]=='N')
nanzhuruqin(i);
else if(pai[i][l[i]]=='J')
break;
else if(pai[i][l[i]]=='Z')
wuqi[i]=142857;//相当于无限出杀
else//防止有一堆杀但是只能出一张的情况或手里没牌
break;
}
}
}
if(check()==1)
cout<<"MP\n";
else
cout<<"FP\n";
for(int i=1;i<=n;i++){
if(dead[i])
cout<<"DEAD\n";
else{
for(int j=l[i];j<=r[i];j++)
cout<<pai[i][j]<<' ';
cout<<"\n";
}
}
return 0;
}
```
同一天 $13:32$:
成功优化 CE,但是 T 了。
```cpp
#include<bits/stdc++.h>
using namespace std;
int wuqi[15];//可出杀的数量
int n,m,qq=1,xue[15];//q表示当前牌堆已发至第几张牌,xue[]表示当前角色血量
bool q,p;
string a[15],g[15];//g[]表示目前该角色标明的身份
bool dead[15];//该猪是否死亡
char pai[15][2005],pd[2005];//pd[]为牌堆
int l[15],r[15];//用char数组pai来代替queue,其中l[],r[]表示左右端点
bool wuxiekeji(int idx){//是否能出一张无懈可击
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='J'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
g[idx]=a[idx];//重点!表敌意和献殷勤实际上就是跳忠或跳反
return qq=true;
}
}
return qq=false;
}
bool biaodiyi(int idx){//献殷勤的猪是idx
for(int i=1;i<=n;i++){
if(g[idx]=="FP" && a[i]=="ZP" || g[idx]=="ZP" && a[i]=="FP" || g[idx]=="FP" && a[i]=="MP" || a[idx]=="MP" && g[i]=="FP"){//注意这里不存在类反猪,因为类反猪在献殷勤是一定被主猪重新认识了
if(wuxiekeji(i)){
g[i]=a[i];//同wuxiekeji()里的这句
return p=true;
}
}
}
return p=false;//失败了
}//注意这里的表敌意单指抵消献殷勤
bool xianyinqin(int idx){//是否成功献殷勤
for(int i=1;i<=n;i++){
if((g[idx]=="FP" && a[i]=="FP") || (g[idx]=="ZP" && a[i]=="ZP") || (g[idx]=="ZP" && a[i]=="MP") || (a[idx]=="MP" && g[i]=="ZP")){
qq=p=false;
while(wuxiekeji(i) && biaodiyi(i)){//出了但是被挡下了
g[i]=a[i];//同wuxiekeji()里的这句
}
if(qq && !p){//出了但是没被挡下
g[i]=a[i];//同上
return true;
}
}
}
return false;//献殷勤失败
}
int check(){//判断是否结束且目前胜者的函数
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]=="FP" && !dead[i]){//该猪是反猪且没有死亡
flag=0;//则主猪、忠猪没有胜利
break;
}
if(flag)
return flag;//已结束且主猪、忠猪胜利了
if(dead[1])
return 2;//主猪死亡,反猪胜利
return 0;
}
void kouxue(int i,int idx){//扣血函数,i为伤害来源
xue[idx]--;
if(xue[idx]==0){
for(int i=l[idx];i<=r[idx];i++){//是否能吃桃补救
if(pai[idx][i]=='P'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
xue[idx]++;//补救成功了
return ;
}
}
dead[idx]=true;//失败了,则该猪死亡
}
if(dead[idx]==true){
if(a[idx]=="FP"){//杀死反猪,摸三张牌
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
if(q!=m)
pai[i][r[i]++]=q++;
}
if(a[idx]=="ZP" && a[i]=="MP"){//主猪杀死了忠猪
l[i]=r[i]=1;
pai[i][l[i]]='1';//模拟清空所有牌
}
}
if(a[idx]=="MP" && g[i]!="ZP")//还没跳忠的猪攻击了主猪
g[i]="LFP";
}
void shan(int i,int idx){//出一张闪
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='D'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void shaa(int i,int idx){//同shan()
for(int i=l[idx];i<=r[idx];i++){
if(pai[idx][i]=='K'){
for(int j=i-1;j>=l[idx];j--)
pai[idx][j+1]=pai[idx][j];
l[idx]++;
return ;
}
}
kouxue(i,idx);//扣血
}
void sha(int idx){
int F=0,qqq=0;
for(int i=2;i<=n;i++)//找离主猪最近的向左可以攻击到主猪的猪
if(!dead[i]){
qqq=i;
break;
}
for(int i=idx+1;i<=n;i++)
if(!dead[i]){
F=i;
break;
}
if(!F)
for(int i=1;i<idx;i++)
if(!dead[i]){
F=i;
break;
}
if(a[idx]=="MP"){
if(g[F]=="LFP" || g[F]=="FP"){//类反猪或反猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
}
}
if(a[idx]=="ZP"){//同主猪
if(g[F]=="LFP" || g[F]=="FP"){//类反猪或反猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
g[F]="ZP";//跳忠
}
}
if(a[idx]=="FP"){//杀忠猪或主猪
if(idx==qqq){//可以向左攻击到主猪
while(!dead[1] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀主猪
l[idx]++;
shan(idx,1);
}
g[F]="FP";//跳反
return ;
}
if(a[F]=="MP" || a[F]=="ZP"){//忠猪或主猪
while(!dead[F] && pai[idx][l[idx]]=='K' && wuqi[idx]>0){//一直杀这只猪
l[idx]++;
shan(idx,F);
}
g[F]="FP";//跳反
}
}
}
void duisha(int i,int j){//到i出杀
if(a[i]=="ZP" && a[j]=="MP"){//若发起者为主猪且接受者为忠猪,则忠猪直接扣血
kouxue(j,i);
return ;
}
int q=xue[i];
shaa(j,i);//出一张杀
if(q==xue[i])
duisha(j,i);//对调,到j出杀
}
void juedou(int idx){
if(a[idx]=="FP"){//注意反猪需要单独拎出来
duisha(1,idx);//无条件攻击主猪
g[idx]="FP";//跳反
return ;
}
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx){
if(a[idx]=="MP" && (g[i]=="LFP" || g[i]=="FP")){//攻击反猪或类反猪
while(pai[idx][l[idx]]=='F' && !xianyinqin(i)){//没人给他献殷勤
duisha(i,idx);//开始决斗
l[idx]++;
}
break;//只对其表敌意
}
if(a[idx]=="ZP" && (g[i]=="LFP" || g[i]=="FP")){//同主猪
while(pai[idx][l[idx]]=='F' && !xianyinqin(i)){//同上
duisha(i,idx);//开始决斗
l[idx]++;
}
g[idx]="ZP";//跳忠
break;//只对其表敌意
}
}
}
}
void wanjianqifa(int idx){
while(pai[idx][l[idx]]=='W'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx && !xianyinqin(i))//没人给他献殷勤
shan(idx,i);//出一张闪
}
}
}
void nanzhuruqin(int idx){
while(pai[idx][l[idx]]=='N'){
l[idx]++;
for(int i=1;i<=n;i++){
if(!dead[i] && i!=idx && !xianyinqin(i))//没人给他献殷勤
shaa(idx,i);//出一张杀
}
}
}
int main(){
cin>>n>>m;
g[1]="MP";
for(int i=1;i<=n;i++){
cin>>a[i]>>pai[i][0]>>pai[i][1]>>pai[i][2]>>pai[i][3];
l[i]=1;//左端点置为1
r[i]=4;//右端点置为4
xue[i]=4;
}
for(int i=1;i<=m;i++)
cin>>pd[i];
while(!check()){
for(int i=1;i<=n;i++){
if(wuqi[i]==0)//重置,注意这里不需重置有武器的情况
wuqi[i]=1;
pai[i][r[i]++]=pd[q++];//摸牌阶段
if(q!=m)
pai[i][r[i]++]=pd[q++];//摸牌阶段
while(true){
if(pai[i][l[i]]=='P')
if(xue[i]!=4){
xue[i]++;
l[i]++;
}else
break;
else if(pai[i][l[i]]=='D')
break;
else if(pai[i][l[i]]=='K' && wuqi[i]>0)
sha(i);
else if(pai[i][l[i]]=='F')
juedou(i);
else if(pai[i][l[i]]=='W')
wanjianqifa(i);
else if(pai[i][l[i]]=='N')
nanzhuruqin(i);
else if(pai[i][l[i]]=='J')
break;
else if(pai[i][l[i]]=='Z')
wuqi[i]=142857;//相当于无限出杀
else//防止有一堆杀但是只能出一张的情况或手里没牌
break;
}
}
}
if(check()==1)
cout<<"MP\n";
else
cout<<"FP\n";
for(int i=1;i<=n;i++){
if(dead[i])
cout<<"DEAD\n";
else{
for(int j=l[i];j<=r[i];j++)
cout<<pai[i][j]<<' ';
cout<<"\n";
}
}
return 0;
}
```