洛谷P2482 [SDOI2010]猪国杀——题解

时间:2024-06-29 00:08:14

猪国杀,模拟题的一颗耀眼的明珠,成长大牛、锻炼码力必写题!

模拟题没什么思维难度。只要按部就班地去做就是。模拟简单在这,难也在这。因为题面巨长,条件巨多,忽疏一点都有可能全盘皆输。故推荐考试时碰见了,除非真的闲的没事,否则尽量不要碰。一旦陷入细节混乱的深渊,估计一上午/下午的考试就混过去了。

总结一下做题的注意点:

  1、审题是最基本的!

     做大模拟题时,必须要认真读题,可能的话,要把所有条件都列举出来(不然就会像我一样,调了一上午才发现就是忘了几个题目中提到的条件或要求)。

  2、理清思路。

     不要吝啬草稿纸,把框架、注意点都写出来。相信我,除非您是AKIOI/NOI/CSP很强的大佬,否则在敲了几百行代码后,肯定会忘了些什么的。而忘了的,都会成为事后艰难调试的根源之一。
     同时,写代码时推荐多利用自定义函数,变量名尽量都用自己熟悉的、见名知意的。这样不仅使程序层次清晰、易于理解,还方便后期的调试(不然写了500行代码后再回来看a1,a2..什么的自己都不知道意义的变量,想死的心都有了)

  3、对于本题来说,找准对象、明确不同对象之间行为的差别也是很有必要的。这种细节特别容易忘,而找起来不留意的话也很难找。

接下来说一下我犯过的容易掉的坑吧,注意一下,这也算是这片题解的主体(没准您就掉进这些坑中呢?):

  1、杀死反猪后会摸牌,要注意猪能否再出牌

  2、 反猪决斗优先打主公(读题)

  3、决斗可能会自杀

  4、决斗只能在第一个人出杀前被无懈可击掉

  5、要注意用牌的顺序(从左到右),以便输出

  6、杀、决斗、无懈可击都会标明身份,南猪入侵和万箭齐发顶多在未表明身份时被主猪认为类反贼

  7、决斗时,主公认为对面是类反贼,实际上是忠臣的情况下,忠臣要牺牲一滴血(连无懈可击也不能出)

  8、当自己没表明身份时,不能对自己用无懈可击

  9、牌能用,要先把用牌的标记打上,免得主杀忠弃牌后再打标记导致错误

  10、装上猪哥连弩有可能使前面的杀能用

  11、中途有新的猪表明身份后,也有可能能让前面的决斗或杀能用。

  12、要每次都用最左边的能用的牌,是对全体来说,而不是对某种来说!

  13、“无懈可击:在目标锦囊生效前抵消其效果。每次有一张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会”。这一点与三国杀不同,三国杀是从锦囊牌的对象开始的。但这里是猪国杀

  14、for循环后i会+1,如重新从左到右看牌,i不能取1,要取0。

  15、当牌堆没有牌时,会一直摸最后一张牌。(这就是RE点的原因吧)

 #include<iostream>
#include<cstdio>
#include<cstring> using namespace std; const int N=,M=; int n,m,win,top,fan,usesha,liangshengfen; char ch,pai; bool vis[N][M],allsf[N]; struct PIG{
int liv,rit,tot,iden,leifan,biao,zhuge,xie;
int wuxie,sha,shan,tao;
char card[M+];
int used[M+];
}pig[N]; char Card[M],sf[]; inline char readch()
{
ch=getchar();
while(ch<'A'||ch>'Z')
ch=getchar();
return ch;
} inline void init()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
{
pig[i].liv=;pig[i].xie=;
scanf("%s",sf);
switch(sf[])
{
case 'M':pig[i].iden=;pig[i].biao=;break;
case 'Z':pig[i].iden=;break;
default:
fan++;
}
for(int j=;j<=;++j)
{
pai=readch();
switch(pai)
{
case 'J':
pig[i].wuxie++;break;
case 'K':
pig[i].sha++;break;
case 'D':
pig[i].shan++;break;
case 'P':
pig[i].tao++;break; }
pig[i].tot++;
pig[i].card[++pig[i].rit]=pai;
} }
for(int i=;i<=m;++i)
Card[i]=readch();
top=;
} inline void yongtao(int u)
{
for(int i=;i<=pig[u].rit;++i)
if(!pig[u].used[i]&&pig[u].card[i]=='P')
{
pig[u].used[i]=;
return;
}
} inline void yonggewuxie(int u)
{
for(int i=;i<=pig[u].rit;++i)
if(!pig[u].used[i]&&pig[u].card[i]=='J')
{
pig[u].used[i]=;
return;
}
} inline void yongsha(int u,int ge)
{
if(!ge)
return;
for(int i=;i<=pig[u].rit;++i)
if(!pig[u].used[i]&&pig[u].card[i]=='K')
{
pig[u].used[i]=;
ge--;
if(!ge)
return;
}
} inline void yongshan(int u)
{
for(int i=;i<=pig[u].rit;++i)
if(!pig[u].used[i]&&pig[u].card[i]=='D')
{
pig[u].used[i]=;
return;
}
} int yongwuxie(int u,int good,int sta)//表身份
{
if(pig[u].biao==)
{
if(pig[u].leifan==)
{
if(good) return ;
if(pig[].wuxie)
{
pig[].wuxie--;
pig[].tot--;
yonggewuxie();
if(!yongwuxie(,,)) return ;
else return ;
}
}
else
return ;
}
int k=n,now=sta-;
if(good)
{
while(k--)
{
now++;
if(now>n)
now=;
if(!pig[now].liv) continue;
if((pig[now].iden&)==(pig[u].iden&)&&pig[now].wuxie)
{
pig[now].wuxie--;
pig[now].tot--;
yonggewuxie(now);
if(pig[now].biao==)
pig[now].biao=,liangshengfen=;
if(!yongwuxie(now,,now)) return ;
else return ;
}
}
return ;
}
else
{
while(k--)
{
now++;
if(now>n)
now=;
if(!pig[now].liv) continue;
if((pig[now].iden&)!=(pig[u].iden&)&&pig[now].wuxie)
{
pig[now].wuxie--;
pig[now].tot--;
yonggewuxie(now);
if(pig[now].biao==)
pig[now].biao=,liangshengfen=;
if(!yongwuxie(now,,now)) return ;
else return ;
}
}
return ;
}
} inline void mosanzhang(int u)
{
for(int j=;j<=;++j)
{
pai=Card[top++];
if(top>m) top=m;
switch(pai)
{
case 'J':
pig[u].wuxie++;break;
case 'K':
pig[u].sha++;break;
case 'D':
pig[u].shan++;break;
case 'P':
pig[u].tao++;break;
}
pig[u].tot++;
pig[u].card[++pig[u].rit]=pai;
}
} inline void diaoxie(int u,int now)//u使now掉血,处理死亡(不处理仇恨)
{
pig[now].xie--;
if(pig[now].xie==)
{
if(pig[now].tao)
{
pig[now].xie=;
pig[now].tot--;
pig[now].tao--;
yongtao(now);
}
else
{
pig[now].liv=;
if(pig[now].iden==)
{
win=;
return;
}
if(pig[now].iden==)
{
if(pig[u].iden==)
{
pig[u].zhuge=;
pig[u].tao=pig[u].sha=pig[u].shan=pig[u].wuxie=;
for(int i=;i<=pig[u].rit;++i)
pig[u].used[i]=;
pig[u].rit=pig[u].tot=;
return;
}
}
if(pig[now].iden==)
{
fan--;
if(fan==)
{
win=;
return;
}
mosanzhang(u);
}
}
}
} inline void nanman(int u)//无仇恨,只类反
{
int k=n-,now=u;
while(k--)
{
now++;
if(now>n) now=;
if(!pig[now].liv) continue;
if(!yongwuxie(now,,u))
{
if(pig[now].sha>)
{
pig[now].sha--;
pig[now].tot--;
yongsha(now,);
}
else
{
diaoxie(u,now);
if(pig[now].iden==&&pig[u].biao==)
pig[u].leifan=;
}
}
if(win) return;
}
} inline void wanjian(int u)
{
int k=n-,now=u;
while(k--)
{
now++;
if(now>n)
now=;
if(!pig[now].liv) continue;
if(!yongwuxie(now,,u))
{
if(pig[now].shan>)
{
pig[now].shan--;
pig[now].tot--;
yongshan(now);
}
else
{
diaoxie(u,now);
if(pig[now].iden==&&pig[u].biao==)
pig[u].leifan=;
}
}
if(win) return;
}
} inline int doumubiao(int u)
{
if(!pig[u].iden)
return ;
int now=u,k=n-;
while(k--)
{
now++;
if(now>n)
now=;
if(!pig[now].liv)
continue;
if(pig[now].biao==)
{
if(u==&&pig[now].leifan)
return now;
}
else
{
if((pig[now].iden&)!=(pig[u].iden&))
return now;
}
}
return ;
} inline int juedou(int u,int now)//只计算掉血、杀
{
if(u==&&pig[now].iden)
{
diaoxie(,now);
return ;
}
if(yongwuxie(now,,u))
return ;
if(!pig[now].sha)
{
diaoxie(u,now);
return ;
}
pig[now].sha--;
pig[now].tot--;
yongsha(now,);
// if(yongwuxie(u,1))
// return 0;
if(!pig[u].sha)
{
diaoxie(now,u);
return ;
}
pig[u].sha--;
pig[u].tot--;
yongsha(u,);
if(pig[now].sha>pig[u].sha)
{
pig[now].sha-=pig[u].sha+;
pig[now].tot-=pig[u].sha+;
yongsha(now,pig[u].sha+);
yongsha(u,pig[u].sha);
pig[u].tot-=pig[u].sha;
pig[u].sha=;
diaoxie(now,u);
return ;
}
else
{
pig[u].sha-=pig[now].sha;
pig[u].tot-=pig[now].sha;
yongsha(u,pig[now].sha);
yongsha(now,pig[now].sha);
pig[now].tot-=pig[now].sha;
pig[now].sha=;
diaoxie(u,now);
return ;
}
} inline void zhengli(int u)
{
int ccnt=;
for(int i=;i<=pig[u].rit;++i)
{
if(!pig[u].used[i])
pig[u].card[++ccnt]=pig[u].card[i];
else
pig[u].used[i]=;
}
pig[u].rit=ccnt;
} inline int nengyongsha(int u)
{
int k=n-,now=u;
while(k--)
{
now++;
if(now>n) now=;
if(!pig[now].liv) continue;
if(pig[u].iden==)
{
if(pig[now].biao==)
{
if(pig[now].iden==)
return now;
else
return ;
}
else
if(pig[now].leifan)
return now;
else
return ;
}
if(pig[now].biao==)
return ;
if((pig[now].iden&)!=(pig[u].iden&))
return now;
else
return ;
}
return ;
} inline void chupai(int u)
{
int t;
int weiyongdou=,weiyongsha=,weiyongtao=;
liangshengfen=;
usesha=;
for(int i=;i<=pig[u].rit;++i)
if(!pig[u].used[i])
{
switch(pig[u].card[i])
{
case 'N':
pig[u].tot--;
pig[u].used[i]=;
nanman(u);
break;
case 'F':
if(t=doumubiao(u))
{
pig[u].used[i]=;
pig[u].tot--;
pig[u].biao=;
if(juedou(u,t))//自己掉血
{
if(weiyongtao>)
{
yongtao(u);
pig[u].xie++;
pig[u].tao--;
pig[u].tot--;
weiyongtao--;
}
}
}
else
weiyongdou=;
break;
case 'W':
pig[u].tot--;
pig[u].used[i]=;
wanjian(u);
break;
case 'Z':
pig[u].zhuge=;
pig[u].used[i]=;
pig[u].tot--;
break;
case 'D':break;
case 'J':break;
case 'P':
if(pig[u].xie<)
{
pig[u].xie++;
pig[u].tao--;
pig[u].used[i]=;
}
else
weiyongtao++;
break;
case 'K':
if(!usesha||(pig[u].zhuge))
{
if(t=nengyongsha(u))
{
usesha=;
pig[u].biao=;
pig[u].used[i]=;
pig[u].tot--;
pig[u].sha--;
if(pig[t].shan)
{
pig[t].shan--;
yongshan(t);
pig[t].tot--;
}
else
diaoxie(u,t);
}
else
weiyongsha=;
}
else
weiyongsha=;
break;
}
if(!pig[u].liv)
return;
if(win) return;
if(liangshengfen&&weiyongdou)
{
liangshengfen=;weiyongdou=;
i=;
}
else
if(weiyongsha&&(!usesha||pig[u].zhuge)&&nengyongsha(u))
{
weiyongsha=;
i=;
}
}
if(pig[u].rit>(pig[u].tot<<))
zhengli(u);
} int main()
{
init();
int now=;
while(!win)
{
if(pig[now].liv)
{
for(int j=;j<=;++j)
{
pai=Card[top++];
if(top>m) top=m;
switch(pai)
{
case 'J':
pig[now].wuxie++;break;
case 'K':
pig[now].sha++;break;
case 'D':
pig[now].shan++;break;
case 'P':
pig[now].tao++;break;
}
pig[now].tot++;
pig[now].card[++pig[now].rit]=pai;
}
chupai(now);
}
now++;
if(now>n)
now=;
}
if(win==)
printf("MP\n");
else
printf("FP\n");
for(int i=;i<=n;++i)
{
if(!pig[i].liv)
printf("DEAD\n");
else
{
for(int j=;j<=pig[i].rit;++j)
if(!pig[i].used[j])
{
printf("%c ",pig[i].card[j]);
}
putchar('\n');
}
}
return ;
}

580行AC代码警告