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. 入门系列之在Ubuntu 14.04上备份,还原和迁移MongoDB数据库

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由信姜缘 发表于云+社区专栏 MongoDB是最受欢迎的NoSQL数据库引擎之一.它以可扩展,强大,可靠和易于使用而闻名.在本文中,我们 ...

  2. cordova程序加载pdf文件的2种方法(ios/android)

    前言 公司目前的前端架构是微信端由vue全家桶负责h5网站的单页应用,android端和ios端则选择cordova打包成apk和app.其中,有一个业务逻辑是点击某个链接进入pdf的展示,h5的方案 ...

  3. [linux] C语言Linux系统编程-捕获进程信号

    typedef void( *sighandler_t)(int); 1.用typedef给类型起一个别名. 2.为函数指针类型定义别名, 3.函数指针(指向函数的指针) sighandler_t s ...

  4. layui使用 ——父,子页面传值

    页面传值是非常常用的,layui自带弹窗功能,但是内置使用的是location.href 暂时没找到方法条件请求头,所以在后台需要放开拦截器, layer.open({ type : 2, title ...

  5. 【Java】短信信息提取设计

    问题产生:当有要求做信息有效性校验的时候,如何提取短信中有用的信息? 举个例子:有这样一条短信消息: [XXXXXX提醒]尊敬的客户,截止03月21日15:29,您本月套餐中包含手机上网国内流量累计1 ...

  6. 基于 java 【Web安全】文件上传漏洞及目录遍历攻击

    前言:web安全之文件上传漏洞,顺带讲一下目录遍历攻击.本文基于 java 写了一个示例. 原理 在上网的过程中,我们经常会将一些如图片.压缩包之类的文件上传到远端服务器进行保存.文件上传攻击指的是恶 ...

  7. K:栈和队列的比较

    栈和队列的相同点: 都是线性结构,即数据元素之间具有"一对一"的逻辑关系 都可以在顺序存储结构和链式存储结构上进行实现 在时间代价上,插入和删除操作都需常数时间:在空间代价上,情况 ...

  8. lvarchar类型对表结构变更影响

    informix中lvarchar类型设计用于存储中度长度的字符数据(短的常用varchar类型.特别长的字符可用text类型).其默认长度2048byte,最大长度32739byte,是一种可变长度 ...

  9. Sass、Less、Stylus,我选Sass!

    Sass官网 | Sass中文 简介:待添加 Less 简介:待添加 Stylus 简介:待添加

  10. jquery操作select(选中,取值)

    最近工作中总出现select 和 option问题,整理一下,内容大部分源于网络资料 一.基础取值问题 例如<select class="selector"></ ...