1972:[SDOI2010]猪国杀

【题目描述】

《猪国杀》是一种多猪牌类回合制游戏,一共有三种角色:主猪,忠猪,反猪。每局游戏主猪有且只有一只,忠猪和反猪可以有多只,每只猪扮演一种角色。

游戏目的:

主猪(MP):自己存活的情况下消灭所有的反猪。

忠猪(ZP):不惜一切保护主猪,胜利条件与主猪相同。

反猪(AP):杀死主猪。

游戏过程:

游戏开始时候,每个玩家手里都会有4张牌,且体力上限和初始体力都是4。

开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从1,2,3..n,1..的顺序)依次行动。

每个玩家自己的回合可以分为4个阶段:

◎摸牌阶段:从牌堆顶部摸两张牌,依次放到手牌的最右边;

◎出牌阶段:你可以使用0张到任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。当然,要满足如下规则:

1.如果没有猪哥连弩,每个出牌阶段只能使用一次“杀”来攻击;

2.任何牌被使用后被弃置(武器是装备上);

被弃置的牌以后都不能再用,即与游戏无关;

各种牌介绍:

每张手牌用一个字母表示,字母代表牌的种类。

◎基本牌:

『桃(P)』:在自己的回合内,如果自己的体力值不等于体力上限,那么使用一个桃可以为自己补充一点体力,否则不能使用桃;桃只能对自己使用;在自己的回合外,如果自己的血变为0或者更低,那么也可以使用;

『杀(K)』:在自己的回合内,对攻击范围内除自己以外的一名角色使用。如果没有被『闪』抵消,则造成1点伤害。无论有无武器,杀的攻击范围都是1;

『闪(D)』:当你受到杀的攻击时,可以弃置一张闪来抵消杀的效果;

◎锦囊牌:

『决斗(F)』:出牌阶段,对除自己以外任意一名角色使用,由目标角色先开始,自己和目标角色轮流弃置一张杀,首先没有杀可弃的一方受到1点伤害,另一方视为此伤害的来源;

『南猪入侵(N)』:出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置一张杀,否则受到1点伤害;

『万箭齐发(W)』:和南猪入侵类似,不过要弃置的不是杀而是闪;

『无懈可击(J)』:在目标锦囊生效前抵消其效果。每次有一张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会;

效果:用于决斗时,决斗无效并弃置;用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对一个角色产生效果);用于无懈可击时,成为目标的无懈可击被无效。

◎装备牌:

『猪哥连弩(Z)』:武器,攻击范围1,出牌阶段你可以使用任意张杀;

同一时刻最多只能装一个武器;如果先前已经有了一把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器;

特殊事件及概念解释:

◎伤害来源:杀、南猪入侵、万箭齐发的伤害来源均是使用该牌的猪,决斗的伤害来源如上;

◎距离:两只猪的距离定义为沿着逆时针方向间隔的猪数+1。即初始时1和2的距离为1,但是2和1的距离就是n-1。注意一个角色的死亡会导致一些猪距离的改变;

◎玩家死亡:如果该玩家的体力降到0或者更低,并且自己手中没有足够的桃使得自己的体力值回到1,那么就死亡了,死亡后所有的牌(装备区,手牌区)被弃置;

◎奖励与惩罚:反猪死亡时,最后一个伤害来源处(即使是反猪)立即摸三张牌。忠猪死亡时,如果最后一个伤害来源是主猪,那么主猪所有装备牌、手牌被弃置;

◎注意,一旦达成胜利条件,游戏立刻结束,因此即使会摸3张牌或者还有牌可以用也不用执行了。

现在,我们已经知道每只猪的角色、手牌,还有牌堆初始情况,并且假设每个角色会按照如下的行为准则进行游戏,你需要做的就是告诉小猪iPig最后的结果。

几种行为:

◎献殷勤:使用无懈可击挡下南猪入侵、万箭齐发、决斗;使用无懈可击抵消表敌意;

◎表敌意:对某个角色使用杀、决斗;使用无懈可击抵消献殷勤;

◎跳忠:即通过行动表示自己是忠猪。跳忠行动就是对主猪或对某只已经跳忠的猪献殷勤,或者对某只已经跳反的猪表敌意;

◎跳反:即通过行动表示自己是反猪。跳反行动就是对主猪或对某只已经跳忠的猪表敌意,或者对某只已经跳反的猪献殷勤;

忠猪不会跳反,反猪也不会跳忠;不管是忠猪还是反猪,能够跳必然跳;

行动准则:

共性:每个角色如果手里有桃且生命值未满,那么必然吃掉;有南猪入侵、万箭齐发、必然使用;有装备必然装上;受到杀时,有闪必然弃置;响应南猪入侵或者万箭齐发时候,有杀/闪必然弃置;不会对未表明身份的猪献殷勤(包括自己);

特性:

◎主猪:主猪会认为没有跳身份,且用南猪入侵/万箭齐发对自己造成伤害的猪是“类反猪”(没伤害到不算,注意“类反猪”并没有表明身份),如果之后跳了,那么主猪会重新认识这只猪;对于每种表敌意的方式,对逆时针方向能够执行到的第一只“类反猪”或者已跳反猪表;如果没有,那么就不表敌意;决斗时会不遗余力弃置杀;如果能对已经跳忠的猪或自己献殷勤,那么一定献;如果能够对已经跳反的猪表敌意,那么一定表;

◎忠猪:对于每种表敌意的方式,对逆时针方向能够执行到的第一只已经跳反的猪表,如果没有,那么就不表敌意;决斗时,如果对方是主猪,那么不会弃置杀,否则,会不遗余力弃置杀;如果有机会对主猪或者已经跳忠的猪献殷勤,那么一定献;

◎反猪:对于每种表敌意的方式,如果有机会则对主猪表,否则,对逆时针方向能够执行到的第一只已经跳忠的猪表,如果没有,那么就不表敌意;决斗时会不遗余力弃置杀;如果有机会对已经跳反的猪献殷勤,那么一定献;

限于iPig只会用P++语言写A + B,他请你用Pigcal(Pascal)、P(C)或P++(C++)语言来帮他预测最后的结果。

【输入】

输入文件第一行包含两个正整数n(2 <= n <= 10) 和m( m <= 2000),分别代表玩家数和牌堆中牌的数量。数据保证牌的数量够用。

接下来n行,每行5个字符串,依次表示对第i只猪的角色和初始4张手牌描述。编号为1的肯定是主猪。

再接下来一行,一共m个字符串,按照从牌堆顶部到牌堆底部的顺序描述每张牌。

所有的相邻的两个字符串都严格用1个空格隔开,行尾没有多余空格。

【输出】

输出数据第一行包含一个字符串代表游戏结果。如果是主猪胜利,那么输出“MP”,否则输出“FP”。数据保证游戏总会结束。 接下来n行,第i行是对第i只猪的手牌描述(注意只需要输出手牌),按照手牌从左往右的顺序输出,相邻两张牌用一个空格隔开,行末尾没有多余空格。如果这只猪已阵亡,那么只要输出“DEAD”即可。注意如果要输出手牌而没有手牌的话,那么只需输出一个空行。

【样例输入】

3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D

【样例输出】

FP
DEAD
DEAD
J J J J J D

【提示】

样例1说明:第一回合主猪没有目标可以表敌意;接下来忠猪使用了3张南猪入侵,主猪掉了3点体力,并认为该角色为类反猪,3号角色尽管手里有无懈可击,但是因为自己未表明身份,所以同样不能对自己用,乖乖掉3点体力;下一回合反猪无牌可出;接下来主猪对着类反猪爆发,使用4张决斗,忠猪死亡,结果主猪弃掉所有牌;下来反猪摸到一张杀直接杀死主猪获胜。
数据说明:一共20组测试数据,每个点5分。10%的数据没有锦囊牌,另外20%的数据没有无懈可击。

【题解】

模拟。
注意以下几个点
1.对于锦囊牌,先用无懈可击再判定。
2.除了桃以外的所有牌在使用后局面可能会发生一些变化,所以重新从左往右扫正在出牌阶段的猪的手牌。
3.注意忠猪是不会对类反猪表敌意的。
4.扫的时候注意跳过已经死了的猪。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
const char Num_to_char[9]={0,'P','K','D','F','N','W','J','Z'};
int char_to_Num[305];
struct Pig{int card[20005],num,now;//1-P 2-K 3-D 4-F 5-N 6-W 7-J 8-Zbool is_used[20005];int blood,upper_limit_blood;//血量,血量上限 int role;//1-MP 2-ZP 3-FPint other_role_look;//0-Unknow 1-忠猪 2-类反猪 3-反猪 int state;//1-DEADint equipment;//1-Z
}P[15];
int N,M,Now_Card,Card[2005],Num[4],Nxt[15],Lst[15],Stack[2005],top;
bool Attk=0,Use_card=0;
void discard(int id,int Card_id){P[id].is_used[Card_id]=1;}
void getcard(int id,int n){for (int i=1;i<=n;i++) P[id].card[++P[id].num]=Card[Now_Card=(Now_Card==M+1?M:Now_Card)],Now_Card++;}
void gameover(int win){if (win==1) printf("MP\n");else printf("FP\n");for (int i=1;i<=N;i++){if (P[i].state==1){printf("DEAD\n");continue;}int Now=1;while (P[i].is_used[Now]) Now++;if (Now<=P[i].num) printf("%c",Num_to_char[P[i].card[Now]]),Now++;for (int j=Now;j<=P[i].num;j++) if (!P[i].is_used[j]) printf(" %c",Num_to_char[P[i].card[j]]);printf("\n");}exit(0);
}
void kill(int A,int B){ //A kill BP[B].state=1;Num[P[B].role]--;P[B].now=P[B].num+1;P[B].other_role_look=0;if (!Num[1]) gameover(3);if (!Num[3]) gameover(1);if (P[A].role==1&&P[B].role==2){P[A].equipment=0;for (int i=P[A].now;i<=P[A].num;i++) P[A].is_used[i]=1;P[A].now=P[A].num+1;}if (P[B].role==3) getcard(A,3);Nxt[Lst[B]]=Nxt[B];Lst[Nxt[B]]=Lst[B];P[B].role=0;
}
int find_card(int need_find_card_type,int id){for (int i=P[id].now;i<=P[id].num;i++) if (!P[id].is_used[i]&&P[id].card[i]==need_find_card_type) return i;return 0;
}
int find_pig(int role,int L,int R){for (int i=L;i<=R;i++){if (P[i].state==1) continue;if (P[i].other_role_look==role) return i;}return 0;
}
void pd_blood_will_dead(int id){while (P[id].blood<=0){int Card_id=find_card(1,id);if (!Card_id) return ;P[id].blood++;discard(id,Card_id);}
}
void Blood_loss(int BeAttacker,int Attacker,int Sp){P[BeAttacker].blood--;pd_blood_will_dead(BeAttacker);if (P[BeAttacker].blood<=0) kill(Attacker,BeAttacker);if (Sp){if (P[BeAttacker].role==1&&P[Attacker].other_role_look==0) P[Attacker].other_role_look=2;return ;}if (P[BeAttacker].other_role_look==1) P[Attacker].other_role_look=3;if (P[BeAttacker].other_role_look==3) P[Attacker].other_role_look=1;
}
namespace Invulnerable{int find_can_use_Invulnerable(int ForWho,int L,int R){for (int i=L;i<=R;i++) {if (P[i].state==1) continue;if (((ForWho==1&&(P[i].role==1||P[i].role==2))||(ForWho==3&&P[i].role==3))&&find_card(7,i)) return i; }return 0;}bool work_Invulnerable(int User,int A,int B){int Who=find_can_use_Invulnerable(A,User,N);if (!Who) Who=find_can_use_Invulnerable(A,1,User-1);if (!Who) return 0;else {discard(Who,find_card(7,Who));P[Who].other_role_look=A;return !work_Invulnerable(Who,B,A);}}bool use_Invulnerable(int User,int BeUser){if (P[BeUser].other_role_look==1) return work_Invulnerable(User,1,3);else if (P[BeUser].other_role_look==3) return work_Invulnerable(User,3,1);return 0;}
};
namespace use_card{void patch(int id,int C_id){P[id].blood++;discard(id,C_id);}void attack(int id,int C_id,int Change){discard(id,C_id);Use_card=1;int Card_id=find_card(3,Nxt[id]);if (!Card_id) Blood_loss(Nxt[id],id,0);else discard(Nxt[id],Card_id);P[id].other_role_look=Change;}void duel(int id,int target,int C_id){discard(id,C_id);Use_card=1;if (P[target].other_role_look==1) P[id].other_role_look=3;if (P[target].other_role_look==3) P[id].other_role_look=1;if (Invulnerable::use_Invulnerable(id,target)) return ;if (P[target].role==2&&P[id].role==1){Blood_loss(target,id,0);return ;}int Card_id_User=find_card(2,id),Card_id_BeUser=find_card(2,target);while (1){if (Card_id_BeUser) discard(target,Card_id_BeUser),Card_id_BeUser=find_card(2,target);else {Blood_loss(target,id,0);return ;}if (Card_id_User) discard(id,Card_id_User),Card_id_User=find_card(2,id);else {Blood_loss(id,target,0);return ;}}}void AOE(int id,int type,int C_id){discard(id,C_id);Use_card=1;for (int i=id+1;i<=N;i++){if (P[i].state==1) continue;if (Invulnerable::use_Invulnerable(id,i)) continue;int Card_id=find_card(type,i);if (Card_id) discard(i,Card_id);else Blood_loss(i,id,1);}for (int i=1;i<id;i++){if (P[i].state==1) continue;if (Invulnerable::use_Invulnerable(id,i)) continue;int Card_id=find_card(type,i);if (Card_id) discard(i,Card_id);else Blood_loss(i,id,1);}}void equip(int id,int C_id){P[id].equipment=1;discard(id,C_id);}
};
namespace pd{void patch(int id,int C_id){if (P[id].upper_limit_blood>P[id].blood) use_card::patch(id,C_id);}void attack(int id,int C_id){if (Attk&&!P[id].equipment) return ;int target=Nxt[id];if (P[id].role==1&&(P[target].other_role_look==2||P[target].other_role_look==3)) Attk=1,use_card::attack(id,C_id,1);if (P[id].role==2&&P[target].other_role_look==3) Attk=1,use_card::attack(id,C_id,1);if (P[id].role==3&&P[target].other_role_look==1) Attk=1,use_card::attack(id,C_id,3);}void duel(int id,int C_id){if (P[id].role==1){int Who,Whom,RW;Who=find_pig(2,id+1,N);if (!Who) Who=find_pig(2,1,id-1);Whom=find_pig(3,id+1,N);if (!Whom) Whom=find_pig(3,1,id-1);RW=Who;if (!RW) RW=Whom;if (RW>id&&Whom>id&&Whom<RW&&Whom) RW=Whom;if (RW<id&&Whom>id&&Whom) RW=Whom;if (RW<id&&Whom<id&&Whom<RW&&Whom) RW=Whom;if (!RW) return ;use_card::duel(id,RW,C_id);}if (P[id].role==2){int Who;Who=find_pig(3,id+1,N);if (!Who) Who=find_pig(3,1,id-1);if (!Who) return ;use_card::duel(id,Who,C_id);}if (P[id].role==3) use_card::duel(id,1,C_id);}void AOE(int id,int type,int C_id){use_card::AOE(id,type,C_id);}void equip(int id,int C_id){use_card::equip(id,C_id);Use_card=1;}
}
int main()
{freopen("kopk.in","r",stdin);freopen("kopk.out","w",stdout);scanf("%d%d",&N,&M);char_to_Num['P']=1;char_to_Num['K']=2;char_to_Num['D']=3;char_to_Num['F']=4;char_to_Num['N']=5;char_to_Num['W']=6;char_to_Num['J']=7;char_to_Num['Z']=8;for (int i=1;i<=N;i++){char ch[3];Nxt[i]=i+1;Lst[i]=i-1;scanf("%s",ch);switch (ch[0]){case 'M':P[i].role=1;break;case 'Z':P[i].role=2;break;case 'F':P[i].role=3;break;}Num[P[i].role]++;for (int j=1;j<=4;j++){scanf("%s",ch);P[i].card[++P[i].num]=char_to_Num[ch[0]];}P[i].now=1;P[i].blood=P[i].upper_limit_blood=4;}Nxt[N]=1;Lst[1]=N;P[1].other_role_look=1;for (int i=1;i<=M;i++){char ch[3];scanf("%s",ch);Card[i]=char_to_Num[ch[0]];}Now_Card=1;while (1){for (int i=1;i<=N;i++){if (P[i].state==1) continue;getcard(i,2);Attk=0;int Now=P[i].now;for (int j=P[i].now;j<=P[i].num;j++){if (P[i].is_used[j]) continue;switch (P[i].card[j]){case 1:pd::patch(i,j);break;case 2:pd::attack(i,j);break;case 4:pd::duel(i,j);break;case 5:case 6:pd::AOE(i,P[i].card[j]-3,j);break;case 8:pd::equip(i,j);break;                    }if (Use_card) j=P[i].now-1,Use_card=0;}while (P[i].is_used[P[i].now]) P[i].now++;}}return 0;
}

【模拟】【bzoj1972】【SDOI2010】猪国杀相关推荐

  1. bzoj1972: [Sdoi2010]猪国杀

    传送门 这不就是三国杀的猪化版吗? 莫名蛋疼的模拟. 打了一个晚上,真爽 #include<cmath> #include<cstdio> #include<cstdli ...

  2. [luogu P2482] [SDOI2010]猪国杀

    [luogu P2482] [SDOI2010]猪国杀 题目描述 <猪国杀>是一种多猪牌类回合制游戏,一共有三种角色:主猪,忠猪,反猪.每局游戏主猪有且只有一只,忠猪和反猪可以有多只,每只 ...

  3. BZOJ1972:[SDOI2010]猪国杀

    我对模拟的理解:https://www.cnblogs.com/AKMer/p/9064018.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  4. [洛谷P2482][SDOI2010]猪国杀

    题目大意:猪国杀,又一道大模拟题 题解:模拟,对于一个没有玩过三国杀的人来说,一堆细节不知道,写的十分吃力 卡点:无数,不想说什么了,这告诉我要多玩游戏 C++ Code: #include < ...

  5. 洛谷P2482 [SDOI2010]猪国杀 题解

    本来这题打算5.15省选考完之后晚上做的,然而15号考了一天的试,于是放16号晚上做了. 原题传送门 题目分析 猪国杀是一道桌游三国杀的简化版,这道题在代码涉及的知识点上难度很低,主要难度就在于如何实 ...

  6. [SDOI2010] 猪国杀

    NOIp前最后皮一下,祝自己RP++. 从昨天晚上开始写,一直写到现在才A...... 在LXD大佬的帮助下,终于A掉了...... 还发现有两道大模拟,一个是琪露诺的冰雪小屋,一个是杀蚂蚁,有兴趣的 ...

  7. SDOI2010 猪国杀

    题目描述 <猪国杀>是一种多猪牌类回合制游戏,一共有三种角色:主猪,忠猪,反猪.每局游戏主猪有且只有一只,忠猪和反猪可以有多只,每只猪扮演一种角色. 游戏目的: 主猪(MP):自己存活的情 ...

  8. Luogu P2482 [SDOI2010]猪国杀

    Pig Country Kill 很古怪的翻译,不过它确实叫猪(Pig)国(Country)杀(Kill). 我们来好好整理一下这道题目.题面虽较长,但内容基本清晰,只是有部分很Pig的操作部分,很容 ...

  9. 模拟 [Sdoi2010]猪国杀

    题目的可读版本 有那么几个地方需要注意: 1.使用一个锦囊后,先判无懈可击. 2.如果一个猪出完一个牌后,要从头开始看哪个能出(有可能一次出牌后某只猪跳忠或者跳反了,F,K什么的就可以用了.) 3.游 ...

  10. P2482 [SDOI2010]猪国杀 【题解】

    题目简述: 这是一道非常善良的凉心模拟题... <身份>: 主猪(主公):MP 忠猪(忠臣):ZP 反猪(反贼):FP <基本牌>: 杀:K 闪:D 桃:P <锦囊牌&g ...

最新文章

  1. 转:Flash 插件面板 DragonBonesDesignPanel 的绿色安装方法
  2. QIIME 2教程. 28社区Community(2020.11)
  3. 高斯混合模型GMM、核心参数、高斯混合模型GMM的数学形式
  4. 码栈开发手册(四)---编码方式开发(日期相关函数)
  5. 低效能人士的七个习惯
  6. Django Forms实例
  7. 升降压斩波电路matlab,升降压直流斩波电路及matlab仿真.doc
  8. 深度解读OpenYurt:从边缘自治看YurtHub的扩展能力
  9. tomcat相关实验
  10. 洛谷——P2068 统计和
  11. mac上安装搭建Appium环境
  12. VOA 2009.11.19-教育报道-美国大学创入学记录新高
  13. 网管工具 dstat
  14. C#andSql获取当前日期格式
  15. 搜电影和网盘资源网站
  16. xampp中mysql使用教程_XAMPP的安装及使用教程
  17. android照片美颜项目_android 美颜滤镜效果的实现
  18. Matlab许可证过期解决办法
  19. 一年303个漏洞,Chrome被评为“最脆弱”浏览器,Opera 最安全!网友:Opera 还有人用?...
  20. 1分钟搞定ubuntu下配置mysql 奥利给

热门文章

  1. java鼠标点击事件_JavaSE 鼠标事件类(MouseEvent)实现
  2. VSM Studio uln2003驱动步进电机+单按键启保停正反转八拍控制
  3. java 本地方法栈_JVM学习笔记-本地方法栈(Native Method Stacks)
  4. java验证码图片滑动验证码_图片滑动验证码的生成
  5. 我的世界服务器死亡不显示,我的世界 服务器怎么开启死亡不掉落 需要 – 手机爱问...
  6. C++中将字符串转换为数字
  7. postgresql字符串转数字
  8. Jdbc连接数据库做删除操作
  9. 吸顶灯怎么固定天花板_如何将物品固定在天花板上同时不破坏天花板和墙面
  10. 耐磨性在微型导轨中的性能分析