记录编号 |
458293 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[SDOI 2010] 猪国杀 |
最终得分 |
100 |
用户昵称 |
Hzoi_Mafia |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.008 s |
提交时间 |
2017-10-10 21:33:34 |
内存使用 |
0.36 MiB |
显示代码纯文本
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char card[5005],paidui[5005],op[5];//card 所有牌 paidui 牌堆
int pre[5005],nxt[5005],cnt;//牌的链表
int top,bot,m,n;//top 牌堆顶 bot 读入时往牌堆里压
int sumf;//sumf 反贼数量
int zhugong;//主公
bool gameover;
inline char get_card(){
if(top!=m)
++top;
return paidui[top];//听说没牌了要一直摸最后一张
}
inline void kill(int,int);
inline void fight(int,int);
inline void nanman(int);
inline void wanjian(int);
inline void hurt(int,int);
inline void godie(int,int);
inline bool wuxiekeji(int,bool);
struct piggy{
int id,appear,blood,num;//id 身份 1主公 2忠臣 3反贼 appear 跳的情况 0 没跳 1 类反 2跳忠 3跳反 num 几号
int nump,numk,numd,numf,numn,numw,numj;//各牌的数量 p 桃 k 杀 d 闪 f 决斗 n 南蛮 w 万箭 j 无懈
bool zhuge,dead;//诸葛 死没死
int prepig,nxtpig,head,last,now,tmp;//链表 牌的链表
int attack;//首要攻击目标
piggy():appear(0),blood(4),nump(0),numk(0),numd(0),numf(0),numn(0),numw(0),numj(0),head(0),last(0),now(0),attack(0){}
inline void mopai(){//摸一张牌
card[++cnt]=get_card();
pre[cnt]=last;
if(!head)head=last=cnt;
else nxt[last]=cnt,last=cnt;//更新链表
if(card[cnt]=='P')++nump;
if(card[cnt]=='K')++numk;
if(card[cnt]=='D')++numd;
if(card[cnt]=='F')++numf;
if(card[cnt]=='N')++numn;
if(card[cnt]=='W')++numw;
if(card[cnt]=='J')++numj;
}
inline void award(){//杀一个的奖励
mopai(),mopai(),mopai();
}
inline void punish(){//杀错的惩罚
head=last=now=nump=numk=numd=numf=numn=numw=numj=0;
zhuge=false;
}
inline void mopaistage(){//摸牌阶段
mopai(),mopai();
}
inline void use(int x){//打出一张牌
if(card[x]=='P')--nump;
if(card[x]=='K')--numk;
if(card[x]=='D')--numd;
if(card[x]=='F')--numf;
if(card[x]=='N')--numn;
if(card[x]=='W')--numw;
if(card[x]=='J')--numj;
if(x==head&&x==last)head=last=0;
else
if(x==head)
head=nxt[x],pre[head]=0;
else
if(x==last)
last=pre[x],nxt[last]=0;
else
pre[nxt[x]]=pre[x],nxt[pre[x]]=nxt[x];//更新链表
}
inline char get_nxt(){//找下一张牌
if(!now)return 0;
tmp=now;
now=nxt[now];
return card[tmp];
}
inline int findp(){//找桃
now=head;
char tp;
while(tp=get_nxt())
if(tp=='P')
return tmp;
}
inline int findk(){//找杀
now=head;
char tp;
while(tp=get_nxt())
if(tp=='K')
return tmp;
}
inline int findd(){//找闪
now=head;
char tp;
while(tp=get_nxt())
if(tp=='D')
return tmp;
}
inline int findf(){//找决斗
now=head;
char tp;
while(tp=get_nxt())
if(tp=='F')
return tmp;
}
inline int findn(){//找南蛮
now=head;
char tp;
while(tp=get_nxt())
if(tp=='N')
return tmp;
}
inline int findw(){//找万箭
now=head;
char tp;
while(tp=get_nxt())
if(tp=='W')
return tmp;
}
inline int findj(){//找无懈
now=head;
char tp;
while(tp=get_nxt())
if(tp=='J')
return tmp;
}
inline bool qiup(){//尝试出桃,返回是否出成桃
if(nump){
use(findp());
return true;
}
return false;
}
inline bool qiuk(){//尝试出杀
if(numk){
use(findk());
return true;
}
return false;
}
inline bool qiud(){//尝试出闪
if(numd){
use(findd());
return true;
}
return false;
}
inline bool qiuf(){//尝试出决斗
if(numf){
use(findf());
return true;
}
return false;
}
inline bool qiun(){//尝试出南蛮
if(numn){
use(findn());
return true;
}
return false;
}
inline bool qiuw(){//尝试出万箭
if(numw){
use(findw());
return true;
}
return false;
}
inline bool qiuj(){//尝试出无懈
if(numj){
use(findj());
return true;
}
return false;
}
inline void round(){//回合
mopaistage();
// cout<<"mopai is over "<<cnt<<endl;
now=head;
char tp;
bool usedsha(false);
while((tp=get_nxt())&&!gameover){
// cout<<"now the card is "<<tp<<endl;
if(tp=='D'||tp=='J')continue;
if(tp=='P'){
if(blood<4)
++blood,use(tmp);
continue;
}
if(tp=='K'){
if(attack==nxtpig){
if(!usedsha||zhuge){
use(tmp);
kill(num,attack);
usedsha=true;
now=head;
if(gameover)return;
}
}
continue;
}
if(tp=='F'){
if(!attack)continue;
use(tmp);
if(id==3)fight(num,1);
else fight(num,attack);
now=head;
if(gameover||dead)return;//决斗可以自杀
continue;
}
if(tp=='N'){
use(tmp);
nanman(num);
now=head;
if(gameover)return;
continue;
}
if(tp=='W'){
use(tmp);
wanjian(num);
now=head;
if(gameover)return;
continue;
}
if(tp=='Z'){
use(tmp);
zhuge=true;
now=head;//从头开始出,因为诸葛可以让前面的杀出来,前面的也是这个作用
continue;
}
}
}
inline void print(){
if(dead)puts("DEAD");
else{
while(head){
printf("%c",card[head]);
if(head!=last)putchar(' ');
head=nxt[head];
}
puts("");
}
}
}a[15];
inline void cal_attack(int x){//计算攻击目标
int y(a[x].nxtpig);
if(a[x].id==1){
while(y!=x){
if(a[y].appear==1||a[y].appear==3){
a[x].attack=y;
return;
}
y=a[y].nxtpig;
}
}
if(a[x].id==2){
while(y!=x){
if(a[y].appear==3){
a[x].attack=y;
return;
}
y=a[y].nxtpig;
}
}
if(a[x].id==3){
while(y!=x){
if(a[y].appear==2||a[y].id==1){
a[x].attack=y;
return;
}
y=a[y].nxtpig;
}
}
a[x].attack=0;
}
inline void allcal(){//所有猪计算一遍
int x(a[zhugong].nxtpig);
cal_attack(zhugong);
while(x!=zhugong){
cal_attack(x);
x=a[x].nxtpig;
}
}
inline void hurt(int x,int y){//x对y造成伤害
--a[y].blood;
// cout<<"now "<<x<<" hurt "<<y<<endl;
if(!a[y].blood){
if(a[y].qiup())++a[y].blood;
else godie(x,y);
}
}
inline void godie(int x,int y){//x杀死了y
a[y].dead=true;
if(a[y].id==1){
gameover=true;
return;
}
if(a[y].id==3){
--sumf;
if(!sumf){
gameover=true;
return;
}
a[x].award();
}
if(a[y].id==2&&a[x].id==1)
a[x].punish();
a[a[y].prepig].nxtpig=a[y].nxtpig;
a[a[y].nxtpig].prepig=a[y].prepig;
allcal();
}
inline void kill(int x,int y){//x对y使用了一张杀
if(a[x].id!=1&&a[x].appear<2){
if(a[y].id==3)a[x].appear=2;
else a[x].appear=3;
allcal();
}
if(a[y].qiud())return;
hurt(x,y);
}
inline void fight(int x,int y){//x对y决斗
if(a[x].id!=1&&a[x].appear<2){
if(a[y].id==3)a[x].appear=2;
else a[x].appear=3;
allcal();
}
if(a[y].id==1||a[y].appear==2)
if(wuxiekeji(x,0))
return;
if(a[y].appear==3)
if(wuxiekeji(x,1))
return;
if(a[x].id==1&&a[y].id==2){
hurt(x,y);
return;
}
while(1){
if(!a[y].qiuk()){
hurt(x,y);
return;
}
if(!a[x].qiuk()){
hurt(y,x);
return;
}
}
}
inline void nanman(int x){//x使用了南蛮
int y(a[x].nxtpig);
// cout<<"now "<<x<<" is nanmaning"<<endl;
while(y!=x){
if(a[y].id==1||a[y].appear==2)
if(wuxiekeji(x,0)){
// cout<<"wuxiekeji "<<y<<endl;
y=a[y].nxtpig;
continue;
}
if(a[y].appear==3)
if(wuxiekeji(x,1)){
// cout<<"wuxiekeji "<<y<<endl;
y=a[y].nxtpig;
continue;
}
if(!a[y].qiuk()){
hurt(x,y);
if(gameover)return;
if(y==1&&a[x].appear==0){
a[x].appear=1;
allcal();
}
}
y=a[y].nxtpig;
}
}
inline void wanjian(int x){//x使用了万箭
int y(a[x].nxtpig);
while(y!=x){
if(a[y].id==1||a[y].appear==2)
if(wuxiekeji(x,0)){
y=a[y].nxtpig;
continue;
}
if(a[y].appear==3)
if(wuxiekeji(x,1)){
y=a[y].nxtpig;
continue;
}
if(!a[y].qiud()){
hurt(x,y);
if(gameover)return;
if(y==1&&a[x].appear==0){
a[x].appear=1;
allcal();
}
}
y=a[y].nxtpig;
}
}
inline bool wuxiekeji(int pos,bool fan){
bool st(fan);
int last(pos),x(pos);
if(fan==(a[x].id==3)){
if(a[x].qiuj()){
last=x;
fan=!fan;
if(a[x].appear<=2){
a[x].appear=3-fan;
allcal();
}
}
}
x=a[x].nxtpig;
while(x!=last){
if(fan==(a[x].id==3)){
if(a[x].qiuj()){
last=x;
fan=!fan;
if(a[x].appear<=2){
a[x].appear=3-fan;
allcal();
}
}
}
x=a[x].nxtpig;
}
return st!=fan;
}
int main(){
freopen("kopk.in","r",stdin);
freopen("kopk.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
a[i].prepig=i-1,a[i].nxtpig=i+1;
a[1].prepig=n,a[n].nxtpig=1;
for(int i=1;i<=n;++i){
scanf("%s",op);
if(op[0]=='M')a[i].id=1,zhugong=i;
if(op[0]=='Z')a[i].id=2;
if(op[0]=='F')a[i].id=3,++sumf;
for(int j=1;j<=4;++j){
scanf("%s",op);
paidui[++bot]=op[0];
}
}
for(int i=1;i<=m;++i){
scanf("%s",op);
paidui[++bot]=op[0];
}
m+=(n<<2);
for(int i=1;i<=n;++i){
a[i].mopaistage();
a[i].mopaistage();
a[i].num=i;
}
allcal();
int now(1);
while(!gameover){
// cout<<"now start "<<now<<" turn"<<endl;
a[now].round();
now=a[now].nxtpig;
// cout<<"check the blood"<<endl;
// for(int i=1;i<=n;++i)
// cout<<i<<" is "<<((a[i].dead)?"dead\0":"live\0")<<" blood "<<a[i].blood<<endl;
}
if(a[zhugong].dead)puts("FP");
else puts("MP");
for(int i=1;i<=n;++i)
a[i].print();
}