题解:P11601 『Fwb』狼人の杀戮
haoyan1103 · · 题解
超级大模拟!!
进入正题
这道题细节很多,注意看以下几点:
- 对象不存在或已死亡。
- 狼人、女巫、猎人自己杀自己。
- 狼人、女巫在一个晚上使用多次技能。
- 平民使用技能。
- 猎人未杀死就使用技能或带走多人。
还有一些特殊的:
女巫使用解药时一定要判断玩家是否是今夜死亡的我被这个点坑了好久。
接下来模拟就行了。
还有多测一定要清空。
上代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n;
int m;
int a[25];//狼人: 1 ;平民: 2 ;猎人: 3 ;女巫: 4
bool witch[25][2];
bool witch_k[25][2];//女巫的毒药和解药
bool vis[25];//狼人和女巫的技能
bool hunter_k[25];
bool hunter[25];//猎人的技能
bool del_k[25];
bool del[25];//标记死亡情况
int op[25],id1[25],id2[25];
set<int> d;//今夜死亡的玩家
bool pd(int id)
{
for(auto i:d)
{
if(i==id)return 0;
}
return 1;
}//判断是否是今夜死亡
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t>>n;
for(int i=1;i<=n;i++)cin>>a[i];
while(t--)
{
bool flag=0;
d.clear();
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)del[i]=del_k[i];
for(int i=1;i<=n;i++)hunter[i]=hunter_k[i];
for(int i=1;i<=n;i++)witch[i][0]=witch_k[i][0],witch[i][1]=witch_k[i][1];
//初始化
cin>>m;
for(int i=1;i<=m;i++)cin>>op[i]>>id1[i]>>id2[i];
for(int i=1;i<=m;i++)
{
if(a[id1[i]]==0 || a[id2[i]]==0){flag=1;break;}//错误直接退出
//判断id合法
if(a[id1[i]]==2){flag=1;break;}//平民使用技能
if(op[i]==0)
{
//判断 1.狼人已死亡 2.杀死人 3.技能今晚已经用过 4.杀自己 5.非狼人杀人
if(del[id1[i]]==1 || del[id2[i]]==1 || vis[id1[i]]==1 || id1[i]==id2[i] || a[id1[i]]!=1){flag=1;break;}
else
{
del[id2[i]]=1;
d.insert(id2[i]);//标记杀死
vis[id1[i]]=1;//标记已使用技能
}
}
else if(op[i]==1)
{
// 1.女巫已死亡 2.杀死人 3.技能今晚已经用过 4.杀自己 5.非女巫毒人
if(del[id1[i]]==1 || del[id2[i]]==1 || witch[id1[i]][0]==1 || id1[i]==id2[i] || a[id1[i]]!=4 || vis[id1[i]]==1){flag=1;break;}
else
{
del[id2[i]]=1;
d.insert(id2[i]);
witch[id1[i]][0]=1;//标记毒死
vis[id1[i]]=1;//标记已使用技能
}
}
else if(op[i]==2)
{
if(del[id2[i]]==0 || witch[id1[i]][1]==1 || a[id1[i]]!=4 || vis[id1[i]]==1){flag=1;break;}// 1.非女巫救人 2.解药用完了 3.已使用技能
else if(del[id1[i]]==1 && (id1[i]!=id2[i] || pd(id1[i]))){flag=1;break;}// 自己死了不救自己
else if(pd(id2[i])){flag=1;break;}//不是当晚死亡
else
{
del[id2[i]]=0;//标记救活
witch[id1[i]][1]=1;
vis[id1[i]]=1;//标记已使用技能
if(a[id2[i]]==3)hunter[id2[i]]=0;
d.erase(id2[i]);
}
}
else if(op[i]==3)
{
// 1.猎人未死 2.带走多人 3.带走自己 4.非猎人带走人
if(del[id1[i]]==0 || hunter[id1[i]]==1 || del[id2[i]]==1 || id1[i]==id2[i] || a[id1[i]]!=3 || pd(id1[i])){flag=1;break;}
else
{
del[id2[i]]=1;
d.insert(id2[i]);//标记带走
hunter[id1[i]]=1;//标记已使用技能
}
}
}
for(int i=1;i<=n;i++)
{
if(del[i]==1 && a[i]==3 && hunter[i]==0){flag=1;break;}
}//判断猎人已死但没带走人
if(flag==1)
{
cout<<"Wrong\n";
continue;
}//不合法
for(int i=1;i<=n;i++)del_k[i]=del[i];
for(int i=1;i<=n;i++)hunter_k[i]=hunter[i];
for(int i=1;i<=n;i++)witch_k[i][0]=witch[i][0],witch_k[i][1]=witch[i][1];
//合法,更新数据
if(d.size()<=0)
{
cout<<"Safe\n";
continue;
}//平安夜
cout<<d.size()<<" ";
for(auto i:d)cout<<i<<" ";
cout<<"\n";
}
return 0;
}