1972: [Sdoi2010]猪国杀

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 364  Solved: 204
[Submit][Status][Discuss]

Description

概述

 
 
《猪国杀》是一种多猪牌类回合制游戏,一共有三种角色:主猪,忠猪,反猪。
 
 
每局游戏主猪有且只有一只,忠猪和反猪可以有多只,每只猪扮演一种角色。
 
 
游戏目的
 
 
主猪(MP):自己存活的情况下消灭所有的反猪。
 
 
忠猪(ZP):不惜一切保护主猪,胜利条件与主猪相同。
 
 
反猪(AP):杀死主猪。
 
 
游戏过程
 
 
游戏开始时候,每个玩家手里都会有 4 张牌,且体力上限和初始体力都是 4 。
 
 
开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从 1, 2, 3...n, 1... 的顺序)依次行动。
 
 
每个玩家自己的回合可以分为 4 个阶段
 
 
摸牌阶段
 
 
从牌堆顶部摸两张牌,依次放到手牌的最右边。
 
 
出牌阶段
 
 
你可以使用 0 张到任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。
 
 
当然,要满足如下规则
 
 
如果没有猪哥连弩,每个出牌阶段只能使用一次“杀”来攻击。
 
 
任何牌被使用后被弃置(武器是装备上)。
 
 
被弃置的牌以后都不能再用,即与游戏无关。
 
 
各种牌介绍
 
 
每张手牌用一个字母表示,字母代表牌的种类。
 
 
基本牌
 
 
『桃(P)』
 
 
在自己的回合内,如果自己的体力值不等于体力上限,那么使用一个桃可以为自己补充一点体力;否则不能使用桃。
 
 
桃只能对自己使用。
 
 
在自己的回合外,如果自己的血变为 0 或者更低,那么也可以使用。
 
 
『杀(K)』
 
 
在自己的回合内,对攻击范围内除自己以外的一名角色使用。
 
 
如果没有被『闪』抵消,则造成 1 点伤害。
 
 
无论有无武器,杀的攻击范围都是 1。
 
 
『闪(D)』
 
 
当你受到杀的攻击时,可以弃置一张闪来抵消杀的效果。
 
 
锦囊牌
 
 
『决斗(F)』
 
 
出牌阶段,对除自己以外任意一名角色使用,由目标角色先开始,自己和目标角色轮流弃置一张杀,首先没有杀可弃的一方受到1点伤害,另一方视为此伤害的来源。
 
 
『南猪入侵(N)』
 
 
出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置一张杀,否则受到1点伤害。
 
 
『万箭齐发(W)』
 
 
和南猪入侵类似,不过要弃置的不是杀而是闪。
 
 
『无懈可击(J)』
 
 
在目标锦囊生效前抵消其效果。
 
 
每次有一张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会。
 
 
效果
 
 
用于决斗时,决斗无效并弃置。
 
 
用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对一个角色产生效果)。
 
 
用于无懈可击时,成为目标的无懈可击被无效。
 
 
装备牌
 
 
『猪哥连弩(Z)』
 
 
武器,攻击范围 1,出牌阶段你可以使用任意张杀。
 
 
同一时刻最多只能装一个武器。
 
 
如果先前已经有了一把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器。
 
 
特殊事件及概念解释
 
 
伤害来源
 
 
杀、南猪入

Input

第一行包含两个正整数n(2 <= n <= 10) 和m( m <= 2000),分别代表玩家数和牌堆中牌的数量。数据保证牌的数量够用。 接下来n行,每行5个字符串,依次表示对第i只猪的角色和初始4张手牌描述。编号为1的肯定是主猪。 再接下来一行,一共m个字符串,按照从牌堆顶部到牌堆底部的顺序描述每张牌。 所有的相邻的两个字符串都严格用1个空格隔开,行尾没有多余空格。

Output

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

Sample Input

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

Sample Output

FP
DEAD
DEAD
J J J J J D

HINT

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

Source

麻麻我要把这个出题人挂起来裱QAQ!

题解

不想多说啥, 就是个大模拟(难以置信的是这是个省选题?!)

说一下我碰到的几个辣鸡坑爹细节好了

1.抽完牌要强行接着抽最后一张

2.清空主公的牌的时候, 首先注意连弩标记也要重置, 其次还得注意牌面迭代器QAQ(2个点RE到死...)

3.无懈可击在AOE下只对一人有效, 不能解决掉整个锦囊

4.无懈可击的遍历判定只有第一个打出无懈可击的玩家有无懈可击的权利, 如果这张无懈可击被后续的无懈可击无效掉也不会继续给后面的玩家机会

5.BZOJ辣鸡题面只截了一半吃枣药丸...可读题面

6.反贼的所有决斗无条件扔给主公

7.杀/决斗/无懈可击都是跳身份的标志, 而且只能对显露身份的玩家使用

然后就是自己的思博错误: 南蛮入侵和万箭齐发的时候如果被无懈可击掉的话判定点不会继续迭代而会消耗掉所有无懈可击QAQ

参考代码

GitHub

 #include <list>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> struct Card; struct Pig{
Pig(int);
int ID;
int HP;
bool LN;
bool JMP,APL;
bool MP,AP,ZP;
Pig* prev;
Pig* next;
void Jump();
void Clear();
void Round();
void Print();
void Arrows();
void SetAPL();
void Die(Pig*);
void Invasion();
void GetCard(int);
void GetHurt(Pig*);
bool Kill();
bool TryDuel();
bool UseKill();
bool UseMiss();
bool UsePeach();
bool JFor(bool);
bool Duel(Pig*);
bool UseCard(char);
bool FindJBecauseOf(Pig*);
std::list<Card*> cards;
}; struct Card{
Card();
char type;
bool Act(Pig*);
}; int n;
int m;
int APs;
bool END;
char last;
char buf[];
std::vector<Pig*> v; void Initialize(); int main(){
Initialize();
Pig* root=v[];
while(!END){
root->Round();
root=root->next;
}
if(APs==)
puts("MP");
else
puts("FP");
for(std::vector<Pig*>::iterator i=v.begin();i!=v.end();++i)
(*i)->Print();
return ;
} bool Pig::Kill(){
if(this->AP){
if(this->next==v[]||(this->next->ZP&&this->next->JMP)){
this->JMP=true;
if(!this->next->UseMiss())
this->next->GetHurt(this);
return true;
}
}
else if(this->MP){
if(this->next->JMP){
if(this->next->AP){
if(!this->next->UseMiss())
this->next->GetHurt(this);
return true;
}
}
else{
if(this->next->APL){
if(!this->next->UseMiss())
this->next->GetHurt(this);
return true;
}
}
}
else if(this->ZP){
if(this->next->AP&&this->next->JMP){
if(!this->next->UseMiss())
this->next->GetHurt(this);
return true;
}
}
return false;
} bool Pig::TryDuel(){
if(this->AP){
this->JMP=true;
if(!v[]->FindJBecauseOf(this)){
if(v[]->Duel(this))
v[]->GetHurt(this);
else
this->GetHurt(v[]);
}
return true;
}
else if(this->MP){
Pig* root=this->next;
while(root!=this){
if((root->AP&&root->JMP)||(root->APL&&!root->JMP)){
if(!root->FindJBecauseOf(this)){
if(root->Duel(this))
root->GetHurt(this);
else
this->GetHurt(root);
}
return true;
}
root=root->next;
}
}
else if(this->ZP){
Pig* root=this->next;
while(root!=this){
if(root->AP&&root->JMP){
this->JMP=true;
if(!root->FindJBecauseOf(this)){
if(root->Duel(this))
root->GetHurt(this);
else
this->GetHurt(root);
}
return true;
}
root=root->next;
}
}
return ;
} bool Pig::Duel(Pig* source){
if(this->ZP&&source->MP)
return true;
else{
while(true){
if(!this->UseKill())
return true;
if(!source->UseKill())
return false;
}
}
} void Pig::Round(){
this->GetCard();
bool Kused=false;
bool flag=false;
for(std::list<Card*>::iterator i=this->cards.begin();(!this->cards.empty())&&i!=this->cards.end();flag?i:++i){
flag=false;
if(END||this->HP==)
break;
if((*i)->type=='P'&&this->HP<){
this->HP++;
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
}
else if((*i)->type=='N'){
this->Invasion();
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
}
else if((*i)->type=='W'){
this->Arrows();
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
}
else if((*i)->type=='K'&&(!Kused||this->LN)){
if(this->Kill()){
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
Kused=true;
}
}
else if((*i)->type=='F'){
if(this->TryDuel()){
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
}
}
else if((*i)->type=='Z'){
if(!this->cards.empty())
this->cards.erase(i);
i=this->cards.begin();
flag=true;
if(this->LN==false){
this->LN=true;
}
}
}
} bool Pig::JFor(bool AP){
Pig* root=this;
do{
if(root->AP==AP){
if(root->UseCard('J')){
root->JMP=true;
return !root->JFor(!AP);
}
}
root=root->next;
}while(root!=this);
return false;
} bool Pig::FindJBecauseOf(Pig* source){
if((!this->JMP)&&(!this->MP))
return false;
else{
return source->JFor(this->AP);
}
} void Pig::GetHurt(Pig* source){
this->HP--;
if(this->HP<=){
if(this->UsePeach())
this->HP++;
else
this->Die(source);
}
} void Pig::Clear(){
this->LN=false;
this->cards.clear();
} void Pig::Die(Pig* source){
this->prev->next=this->next;
this->next->prev=this->prev;
if(this->MP)
END=true;
else if(this->AP){
APs--;
if(APs<=){
END=true;
return;
}
source->GetCard();
}
else if(this->ZP&&source->MP){
source->Clear();
}
} bool Pig::UseKill(){
return this->UseCard('K');
} bool Pig::UseMiss(){
return this->UseCard('D');
} bool Pig::UsePeach(){
return this->UseCard('P');
} void Pig::SetAPL(){
if(!this->JMP)
this->APL=true;
} bool Pig::UseCard(char ch){
for(std::list<Card*>::iterator i=this->cards.begin();i!=this->cards.end();++i){
if((*i)->type==ch){
this->cards.erase(i);
return true;
}
}
return false;
} void Initialize(){
scanf("%d%d",&n,&m);
m+=*n;
for(int i=;i<n;i++)
v.push_back(new Pig(i));
v[n-]->next=v[];
v[]->prev=v[n-];
for(int i=;i<n;i++){
v[i-]->next=v[i];
v[i]->prev=v[i-];
}
if(APs==)
END=true;
} Pig::Pig(int ID){
this->ID=ID;
this->LN=false;
this->JMP=this->APL=false;
this->AP=this->ZP=this->MP=false;
this->HP=;
scanf("%s",buf);
if(*buf=='M')
this->MP=true;
else if(*buf=='Z')
this->ZP=true;
else
this->AP=true;
this->GetCard();
if(this->AP)
APs++;
} Card::Card(){
if(m>){
scanf("%s",buf);
this->type=*buf;
last=this->type;
m--;
}
else
this->type=last;
} void Pig::Arrows(){
Pig* root=this->next;
while(root!=this){
if(root->FindJBecauseOf(this)){
root=root->next;// QAQ
continue;
}
if(!root->UseMiss()){
if(root->MP)
this->SetAPL();
root->GetHurt(this);
}
if(END)
return;
root=root->next;
}
} void Pig::Invasion(){
Pig* root=this->next;
while(root!=this){
if(root->FindJBecauseOf(this)){
root=root->next;// QAQ
continue;
}
if(!root->UseKill()){
if(root->MP)
this->SetAPL();
root->GetHurt(this);
}
if(END)
return;
root=root->next;
}
} void Pig::GetCard(int cnt){
while(cnt--)
this->cards.push_back(new Card());
} void Pig::Print(){
if(this->HP<=)
puts("DEAD");
else{
while(!this->cards.empty()){
putchar(this->cards.front()->type);
this->cards.pop_front();
if(!this->cards.empty())
putchar(' ');
}
putchar('\n');
}
}

Backup

(补图了补图了)

[BZOJ 1972][Sdoi2010]猪国杀的更多相关文章

  1. 1972: [Sdoi2010]猪国杀 - BZOJ

    题目太长,我只发链接吧 wikioi(排版看起来舒服一点):http://www.wikioi.com/problem/1834/ bzoj:http://www.lydsy.com:808/Judg ...

  2. Luogu2482 [SDOI2010]猪国杀 ---- 模拟

    Luogu2482 [SDOI2010]猪国杀 题意 ...... https://www.luogu.org/problemnew/show/P2482 总结 首先说一下代码的构思: 首先确定了所有 ...

  3. BZOJ1972:[SDOI2010]猪国杀

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

  4. 洛谷 P2482 loj #2885 [SDOI2010]猪国杀 题解【模拟】【贪心】【搜索】

    好玩的模拟题. 以后要经常写模拟题鸭 题目描述 游戏背景 <猪国杀>是一种多猪牌类回合制游戏,一共有\(3\)种角色:主猪,忠猪,反猪.每局游戏主猪有且只有\(1\)只,忠猪和反猪可以有多 ...

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

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

  6. 【BZOJ1972】[SDOI2010] 猪国杀(恶心的大模拟)

    点此看题面 大致题意: 让你模拟一个游戏猪国杀的过程. 几大坑点 对于这种模拟题,具体思路就不讲了,就说说有哪些坑点. 题面有锅,反猪是\(FP\). 数据有锅,牌堆中的牌可能不够用,牌堆为空之后需一 ...

  7. Bzoj1972: [Sdoi2010]猪国杀 题解(大模拟+耐心+细心)

    猪国杀 - 可读版本 https://mubu.com/doc/2707815814591da4 题目可真长,读题都要一个小时. 这道题很多人都说不可做,耗时间,代码量大,于是,本着不做死就不会死的精 ...

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

    猪国杀,模拟题的一颗耀眼的明珠,成长大牛.锻炼码力必写题! 模拟题没什么思维难度.只要按部就班地去做就是.模拟简单在这,难也在这.因为题面巨长,条件巨多,忽疏一点都有可能全盘皆输.故推荐考试时碰见了, ...

  9. Luogu P2482 [SDOI2010]猪国杀

    这道题在模拟界地位不亚于Luogu P4604 [WC2017]挑战在卡常界的地位了吧. 早上到机房开始写,中间因为有模拟赛一直到1点过才正式开始码. 一边膜拜CXR dalao一边写到3点左右,然后 ...

随机推荐

  1. svn 改英文

  2. TimerJob无法发布新版本问题

    最近遭遇发布TimerJob在测试环境发布没有问题,但是到正式环境发布总是无法执行及调试的问题,经过几天的努力,终于解决了这个问题,下面记录下遭遇的问题. Windows 2008,SharePoin ...

  3. 虚拟机安装Ubuntu的上网设置(有线网络和无线网络)

    (恩,是转的) 虚拟机下ubuntu共享方式上网: 一. 有线网络 在有线网络的条件下,vmware的安装非常简单,上网方式几乎不用怎么设置(默认NAT模式)     如果默认情况下不能上网,则按以下 ...

  4. [转]深入Java单例模式

       文章从 https://blog.51cto.com/devbean/203501 转载 问题 : doble-check 实现的单例模式有什么缺点 线程安全的单例写法应该是怎么样的 概述 在G ...

  5. CodeForces 598B(循环数组)

    对于循环数组的问题,就是找偏移K后位置 偏移后位置=起始位置+(相对位置+K)%(长度+1) #include <iostream> #include <string> #in ...

  6. Java 时区转换(UTC+8 到 UTC 等等)

    前言:需要做时区转换,知道北京为UTC+8,东京为UTC+9,世界标准时间为UTC,所以下面的代码是只需要知道时区是+8还是+9还是0就可以了,不需要使用"CTT". " ...

  7. HTTP 错误500.19 - 错误代码 0x80070021

    1.错误描述 HTTP 错误500.19 -Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息 模块 IIS Web Core  通知 Begi ...

  8. 【零基础学习FreeRTOS嵌入式系统】之一:FreeRTOS环境搭建

    [零基础学习FreeRTOS嵌入式系统]之一:FreeRTOS环境搭建 一:FreeRTOS系统下载 在官网上https://www.freertos.org/,找到下载入口. 或直接进入下载地址ht ...

  9. 牛客Wannafly挑战赛11E 白兔的刁难

    传送门 如果大力推单位根反演就可以获得一个 \(k^2logn\) 的好方法 \[ans_{t}=\frac{1}{k}\sum_{i=0}^{k-1}(w_k^{-t})^i(w_k^i+1)^n\ ...

  10. bitset(01串)优化

    bitset的经典使用: 见代码及注释: #include<bitset> #include<algorithm> using namespace std; //只需调用< ...