题目大意

只能放链接了。

题目中有一点没说:并不是保证牌够用,而是在牌不够用时反复抽最后一张牌。

题解

发现玩家的数量比较少,所以可以不太在意时间够不够用。

考虑三件事:1.基本操作,如摸牌、出牌、玩家死亡、牌的效果;2.游戏流程;3.出牌对象。

摸牌、出牌:

发现对于“某玩家的牌”的操作是从左往右扫第一张可用的,然后删掉(出牌),或者往最右放两张(摸牌),这两个操作用链表很好维护。建议把“判断从玩家\(x\)手牌里有没有值为\(k\)的,如果能,就把最左的\(k\)删去”和“在玩家\(x\)手牌最右放两张牌”这两个操作写成两个函数。建议记\(a_i\)表示玩家\(i\)是否装武器。

玩家死亡:

用链表维护每个玩家前后存活的玩家。玩家死亡时,先判手里有没有P,如果有,把血量改为1并复活(因为所有能造成伤害的牌,都只能造成1的伤害,所以不会降到0以下);如果没有,该玩家死亡,如果该玩家是MP或最后一个FP,则游戏结束,否则是FP的话伤害来源摸3张牌,是ZP且伤害来源是MP的话MP的手牌链表清空且令\(a_1=0\)。

牌的效果:

\(x\)对\(y\)出K:\(x\)身份暴露,判断\(y\)是否有D,若有则无事发生,若没有则\(y\)血量减少,判断\(y\)是否死亡。

\(x\)出P:血量+1。

\(x\)出Z:令\(a_x=1\)。

\(x\)出J:\(x\)身份暴露,从\(x\)开始依次判断是否有玩家成功出J,若有,则J被抵消;若没有,\(x\)出的J生效。建议用递归函数实现。

\(x\)出N或W:从\(x\)右边的玩家开始依次判断每个玩家是否会受伤,对于每个玩家,从\(x\)开始依次判断是否有玩家出J,若有则该玩家无事发生,若没有则判断该玩家能不能出K或D,若能则该玩家无事发生,否则该玩家掉血、判断死亡。这两个AOE几乎一样,建议一块写。需要注意的是,自己的AOE打到表明身份的队友时,可能会自己对自己的AOE出J。

\(x\)对\(y\)出F:\(x\)身份暴露,判J,判是否\(x\)为MP且\(y\)为ZP。维护两个指针,分别表示当前考虑到\(x 、 y\)的第几张牌。轮流移动指针至下一个K,如果一方没有K,则该方掉血、判断死亡。

记当前玩家为\(x\),用链表维护每个玩家前后存活的玩家。如果有人死亡则更新死亡者前后的玩家的链表。对于\(x\)的回合,先摸两张牌,再从左往右扫,如果无牌可出则回合结束,否则出牌,然后重新判断是否有牌可出(因为F、AOE出完后可能会有玩家出J,暴露身份,可能导致\(x\)有的牌变得可出)。需要注意\(x\)的回合可能因为\(x\)死亡而中断(\(x\)出F使自己死亡),要记\(x\)该回合是否出过K。

K:对在自己右边相邻的,且已经表明身份,且是敌人的玩家。

F:MP对逆时针方向第一个表明身份的FP或类反猪;ZP对逆时针方向第一个表明身份的FP;FP只会对MP。

J:记\(f(x,y,z)\space z\in\{0,1\}\)表示上一张牌是\(x\)对\(y\)的\(z\)行为(\(z=1\)表示献殷勤,\(z=0\)表示表敌意),是否被抵消。若\(z=1\)且\(k\)认为\(x\)是敌人且\(k\)有J,则\(k\)出J,然后\(f(k,x,0)\)判断该J是否生效;若\(z=0\)且\(k\)认为\(y\)是友军且\(k\)有J,则\(k\)出J,然后\(f(k,y,1)\)判断该J是否生效。注意要在出牌瞬间更改出牌者的“表面身份”,不然会影响到别的玩家是否出J。

想完这些后,下一步就是写了。好像模拟的内容和题目描述稍有不同就会WA一大片……

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define viewcd(u,k) for(int k=nxt[u];k;k=nxt[k])
#define LL long long
#define maxn 17
#define maxm 2007
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int numpg,numcd,cf,stp;
int h[maxn],w[maxn],p[maxn],n[maxn],fake[maxn],real[maxn];
int nxt[maxm<<1],pre[maxm<<1],cntcd,chg;
char c[maxm<<1],C[maxm],s[10];
void addcd(int x,int k)
{
rep(i,1,k)
{
c[++cntcd]=C[numcd--];if(!numcd)numcd=1;
nxt[pre[x]]=cntcd,pre[cntcd]=pre[x],pre[x]=cntcd,nxt[cntcd]=x;
}
}//x gets k cards.
void del(int x,int k)
{
int nk=nxt[k],pk=pre[k];
pre[nk]=pk,nxt[pk]=nk;
}//x lose card k
void clear(){nxt[1]=pre[1]=1;w[1]=0;return;}//x lose its cards.
void kil(int x,int y)
{
if(real[y]==1&&x==1){clear();}
else if(real[y]==3){cf--;if(!cf)stp=1;if(!stp)addcd(x,3);}
else if(y==1)stp=1;
if(stp)return;
int ny=n[y],py=p[y];p[ny]=py,n[py]=ny;
}//x kill y.
int getcd(int x,char tp)
{
for(int k=nxt[x];k!=x;k=nxt[k])
if(tp==c[k]){del(x,k);return 1;}
return 0;
}//get card tp of x.
int reborn(int x){if(!getcd(x,'P'))return 0;h[x]=1;return 1;}//x is going to die.
int enemy(int x,int y){if(((fake[y]&1)&&fake[y]!=real[x])||(x==1&&fake[y]==2))return 1;return 0;}//x wants to kill y.
int nedJ(int x,int y,int f)
{
for(int k=n[x];k!=x;k=n[k])
{
if(!f&&fake[y]==real[k])
{
if(getcd(k,'J'))
{
fake[k]=real[k];
if(!nedJ(k,y,1))return 1;
}
}
if(f&&enemy(k,x))
{
if(getcd(k,'J'))
{
fake[k]=real[k];
if(!nedJ(k,x,0))return 1;
}
}
}
return 0;
}///x use ... on y
//0:enemy;1:friend
int prot(int x,int y)
{
if(fake[y]==real[x]){if(getcd(x,'J')){fake[x]=real[x];if(!nedJ(x,y,1))return 1;}}
for(int k=n[x];k!=x;k=n[k])if(fake[y]==real[k])
{
if(getcd(k,'J'))
{
fake[k]=real[k];
if(!nedJ(k,y,1))return 1;
}
}
return 0;
}//x use ... on y
void K(int x,int y)
{
fake[x]=real[x];
if(!getcd(y,'D')){h[y]--;if(h[y]==0&&!reborn(y))kil(x,y);}
}//
void F(int x,int y)
{
int kx=nxt[x],ky=nxt[y];
fake[x]=real[x];
if(prot(x,y))return;
if(real[y]!=1||x!=1)
{
while(ky!=y)
{
for(;ky!=y;ky=nxt[ky])if(c[ky]=='K')break;
if(c[ky]!='K')break;
del(y,ky),ky=nxt[ky],swap(x,y),swap(kx,ky);
}
}
if((real[y]==1&&x==1)||c[ky]!='K'){h[y]--;if(h[y]==0&&!reborn(y))kil(x,y);}
}//
void AOE(int x,char tp)//tp=='N':'K', tp=='W':'D'
{
char ned=(tp=='N')?'K':'D';
for(int y=n[x];y!=x;y=n[y])if(!prot(x,y))
{
if(!getcd(y,ned))
{
h[y]--;
if(!h[y]&&!reborn(y))kil(x,y);
if(stp)return;
if(y==1&&!fake[x])fake[x]=2;
}
}
}
int main()
{
numpg=read(),numcd=read();cntcd=numpg;
rep(i,1,numpg)
{
scanf("%s",s);pre[i]=nxt[i]=i;
real[i]=(s[0]=='M'||s[0]=='Z')?1:3;fake[i]=(i==1)?1:0;
rep(j,1,4)
{
scanf("%s",s);
c[++cntcd]=s[0];
nxt[pre[i]]=cntcd,pre[cntcd]=pre[i],pre[i]=cntcd,nxt[cntcd]=i;
}p[i]=(i-1)==0?numpg:i-1,n[i]=i==numpg?1:i+1,h[i]=4;
if(real[i]==3) cf++;
}
rep(i,1,numcd){scanf("%s",s);C[numcd-i+1]=s[0];}
if(cf==0)stp=1;
for(int x=1;!stp;x=n[x])
{
addcd(x,2);int mk=0,k;
usecd:
chg=0;
for(k=nxt[x];k!=x;k=nxt[k])
{
if(c[k]=='K'&&(!mk||w[x])&&enemy(x,n[x]))
{
mk=1;del(x,k),K(x,n[x]);chg=1;break;
}
else if(c[k]=='F')
{
int y;
if(real[x]==3){del(x,k),F(x,1);}
else
{
for(y=n[x];y!=x;y=n[y])if(enemy(x,y)){break;}
if(!enemy(x,y))continue;
del(x,k),F(x,y);
}
chg=1;break;
}
else if(c[k]=='N'||c[k]=='W'){del(x,k),AOE(x,c[k]);chg=1;break;}
else if(c[k]=='Z'){del(x,k),w[x]=1;chg=1;break;}
else if(c[k]=='P'&&h[x]<4){del(x,k),h[x]++;}
}
if(chg&&!stp&&h[x]){goto usecd;}
if(stp)break;
}
puts(h[1]>0?"MP":"FP");
rep(i,1,numpg)
{
if(h[i]<=0){printf("DEAD");}
else {for(int k=nxt[i];k!=i;k=nxt[k]){printf("%c ",c[k]);}}
puts("");
}
return 0;
}
一些感想

终于可以肆无忌惮地玩梗了!

并不对劲的bzoj1972:loj2885:p2482[SDOI2010]猪国杀的更多相关文章

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

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

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

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

  3. Luogu P2482 [SDOI2010]猪国杀

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

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

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

  5. [BZOJ 1972][Sdoi2010]猪国杀

    1972: [Sdoi2010]猪国杀 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 364  Solved: 204[Submit][Status][D ...

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

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

  7. BZOJ1972:[SDOI2010]猪国杀

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

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

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

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

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

随机推荐

  1. 牛券Cow Coupons

    USACO12FEB 久违的奶牛题. 题意: FJ准备买一些新奶牛,市场上有 $ N $ 头奶牛 $ (1 \leq N \leq 50000) $ ,第i头奶牛价格为 $ P_i (1 \leq P ...

  2. Innodb内存结构

      聚集索引与非聚集索引: 聚集索引:主键,有序,存储顺序与内存一致 非聚集索引:非主键,无序 聚集索引在叶子节点存储的是表中的数据 非聚集索引在叶子节点存储的是主键和索引列 使用非聚集索引查询出数据 ...

  3. Rsa加密类

    需要导入Base64.jar包 import java.io.ByteArrayOutputStream; import java.security.Key; import java.security ...

  4. Grafana添加Zabbix为数据源(二)

    接触过grafana的同学肯定会觉得grafana比zabbix的图像灵活好看很多,下面就让我们一起进行grafana的web界面配置 1.鼠标移动到左上角,点击Plugins,然后选择"c ...

  5. selenium 常见操作事件2

    1.不打开浏览器驱动(加速) 注意:不启动浏览器器时,需要把浏览器驱动放置以下位置:①.python安装的根目录②.google的安装目录() from selenium import webdriv ...

  6. 更改mysql 数据库 utf8

    mysql> alter database 数据库名 character set utf8;

  7. 小D课堂 - 新版本微服务springcloud+Docker教程_6-02 springcloud网关组件zuul

    笔记 2.SpringCloud的网关组件zuul基本使用     简介:讲解zuul网关基本使用 1.加入依赖 2.启动类加入注解 @EnableZuulProxy         默认集成断路器 ...

  8. IPv6 ping命令

    IPv6 ping命令 一.Linux操作系统 给一台 Linux 主机分配了一个 IPv6 的 IP地址,如何使用 ping命令 确定该 IP地址 能否 ping 通呢? 1.查看主机的 IPv6 ...

  9. 前端学习之JavaScript(1)

    目录 一. JavaScript简介 二. 第一个JavaScript代码 三. 基本数据类型 四. 运算符 五. 数据类型转换 六. 流程控制 七. 常用内置对象 八. 函数 一. JavaScri ...

  10. vue中 key 值的作用

    原文地址 我们知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面.而隐藏在背后的原理便是其高效的Diff算法. vue和react的虚拟DOM ...