PAT 1022 Werewolf PAT顶级(2021天梯赛模拟L3-2狼人杀)
爆搜,按照题意来搜。。。
太难写了,当模拟写的,代码分成了很多块,长度比较难看。。。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
const int inf = 1e9 + 7;
const ll lnf = 1e18 + 7;
const int maxn = 1e6 + 10;
ll mod = 1e9 + 7;
int n, m, l;//总数,还可以选多少狼,还有多少人可以说谎
int a[105];
int isw[105], wl;//是不是狼,有多少狼说谎
void dfs(int now)
{
//输出答案,有格式要求
if (now == 0)
{
if (!wl || m != 0 || l != 0)return;
vector<int>ans;
for (int i = n; i >= 1; i--)
if (isw[i] == 1)
ans.push_back(i);
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i];
if (i < ans.size() - 1)
cout << " ";
}
exit(0);
}
int to = abs(a[now]);
int has = (isw[now] != 0);//之前是否被指认
for (int i = 1; i >= 0; i--)
{
//对isw[now]赋值
if (!has)//之前没被某人指认
{
if (i == 0)
isw[now] = -1;//不是狼
else if (i == 1)
{
if (!m)continue;//不能选狼了
//是狼
m--;
isw[now] = 1;
}
}
if (l&& a[now] * isw[to] >= 0)//有说谎次数,结果与不说谎相反
{
l--;
if(isw[now]==1)//狼说谎
wl++;
bool ok = 0, mflg = 0;//先判指认的人有没有已知身份,再判能不能是狼
bool flag = 1;
if (isw[to] == 0)
{
ok = 1;
if (a[now] < 0)
isw[to] = -1;
else
{
if (m)
isw[to] = 1, m--, mflg = 1;
else
flag = 0;
}
}
if (flag)//之前有不合法状态,不进行搜索
{
dfs(now - 1);
if (ok)
{
if (mflg)m++;
isw[to] = 0;
}
}
l++;
if(isw[now]==1)
wl--;
}
if (a[now] * isw[to] <= 0)//不说谎并且可以为真,从上面复制下来的
{
bool ok = 0, mflg = 0;//先判指认的人有没有已知身份,再判能不能是狼
bool flag = 1;//状态是否合法
if (isw[to] == 0)//isw[to]没被赋值
{
ok = 1;
if (a[now] > 0)
isw[to] = -1;
else
{
if (m)
isw[to] = 1, m--, mflg = 1;
else
flag = 0;//不能是狼,不合法
}
}
if (flag)//之前有不合法状态,不进行搜索
{
dfs(now - 1);
if (ok)//之前有了就不需要回溯
{
if (mflg)
m++;
isw[to] = 0;
}
}
}
if (has)break;//has会在指认他的人处回溯
//回溯isw[now]
isw[now] = 0;
if (i == 1)
m++;
}
}
int main()
{
fastio;
wl = 0;
cin >> n >> m >> l;
for (int i = 1; i <= n; i++)
{
char c;
cin >> c;
cin >> a[i];
if (c == '-')
a[i] = -a[i];
}
dfs(n);
cout << "No Solution";
return 0;
}