题解:P11601 『Fwb』狼人の杀戮

· · 题解

首先,看到这道题的题面,我们根据直觉可以发现这是一道大模拟。但是,这里有一种十分麻烦的操作,就是有可能在那一晚,技能输入有误。

我们来分析一下技能输入有误的情况有那些:

  1. 自己杀自己。
  2. 使用与自己职业不同的技能。
  3. 杀了早已死了的人反复鞭尸
  4. 同一晚发动了多次技能。
  5. 编号有问题。
  6. 女巫没有药还救人或杀人。
  7. 女巫救了早已死透的人。
  8. 女巫救了还活着的人。
  9. 女巫处于将死状态,却不救自己,救别人,舍己为人。

对于这种要撤销的操作,我们把前一次操作前的状态储存下来,要撤销的话就直接使用上一次的状态。

然后模拟即可。

下面是代码环节:

#include<bits/stdc++.h>
using namespace std;
int t, n, a[25];
bool last[25], jie[25], du[25], lajie[25], ladu[25], die[25], lang[25], women[25], lie[25];
set<int> st;
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> t >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        if (a[i] == 4) {
            jie[i] = true;
            du[i] = true;
        }
    }
    for (int kkkk = 1; kkkk <= t; kkkk ++) {
        bool flag = true;
        memset(lang, false, sizeof(lang));
        memset(women, false, sizeof(women));
        memset(lie, false, sizeof(lie));
        st.clear();
        for (int i = 1; i <= n; i ++) {
            last[i] = die[i];
            lajie[i] = jie[i];
            ladu[i] = du[i];
        }
        int m;
        cin >> m;
        for (int i = 1; i <= m; i ++) {
            int op, id1, id2;
            cin >> op >> id1 >> id2;
            if (id1 > n || id1 < 1 || id2 > n || id2 < 1) {
                flag = false;
            }
            if (op == 0) {
                if (a[id1] != 1 || lang[id1] || die[id2] || die[id1] || id1 == id2) {
                    flag = false;
                }
                die[id2] = true;
                lang[id1] = true;
                st.insert(id2);
            } else if (op == 1) {
                if (a[id1] != 4 || !du[id1] || die[id2] || women[id1] || id1 == id2 || die[id1]) {
                    flag = false;
                }
                du[id1] = false;
                die[id2] = true;
                women[id1] = true;
                st.insert(id2);
            } else if (op == 2) {
                if (a[id1] != 4 || !jie[id1] || !die[id2] || women[id1] || last[id2] || last[id1]) {
                    flag = false;
                }
                if (die[id1] && id1 != id2) {
                    flag = false;
                }
                jie[id1] = false;
                die[id2] = false;
                women[id1] = true;
                lie[id2] = false;
                st.erase(id2);
            } else if (op == 3) {
                if (a[id1] != 3 || !die[id1] || id1 == id2 || die[id2] || last[id1] || lie[id1]) {
                    flag = false;
                }
                die[id1] = true;
                die[id2] = true;
                lie[id1] = true;
                st.insert(id2);
            }
        }
        for (auto i : st) {
            if (a[i] == 3 && !lie[i]) {
                flag = false;
            }
        }
        if (!flag) {
            cout << "Wrong\n";
            for (int i = 1; i <= n; i ++) {
                die[i] = last[i];
                jie[i] = lajie[i];
                du[i] = ladu[i];
            }
            continue;
        }
        int len = st.size();
        if (len == 0) {
            cout << "Safe\n";
        } else {
            cout << len << " ";
            for (auto i : st) {
                cout << i << " ";
            }
            cout << "\n";
        }
    }
    return 0;
}