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

· · 题解

upd on 2025/1/22:增加猎人多次开枪情况。

根据题意模拟即可,这里直接总结。

输入会有错误的点

注意

为了简化输入有错后的「撤销」操作考虑新开一个东西存然后 memcpy

code 非常简单,个人认为和 CSP 那道差不多。

#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
#define rep(i, j, k) for(int i = j; i <= k; ++i)
#define pre(i, j, k) for(int i = j; i >= k; --i)
#define pb push_back
using namespace std;
const int N = 66;

int n, m, q, cnt, flg, a[N], b[N], B[N], vis[N];
int tag[N][4], ID;
//1狼 2民 3枪 4女 

bool check(int op, int x, int y) {
    if(!(1 <= x && x <= n) || !(1 <= y && y <= n)) return false;
    //assert(!(x == y && a[x]==4));
    if(a[x] == 4 && x == y && !vis[x] && B[x] && tag[x][3]) return B[x] = 0, vis[x] = 1, tag[x][3] = 0, true;//女巫自救
    else if(a[x] == 4 && x == y) return false;
    if(B[x] && a[x] != 3 || a[x] == 2 || vis[x]) return false;
    if(op == 0)  {//狼刀 
        if(a[x] != 1 || x == y || B[y]) return false;
        B[y] = vis[x] = 1;
    }   
    if(op == 1) {//女毒 
        if(a[x] != 4 || x == y || B[y] || !tag[x][2]) return false;
        B[y] = 1;
        tag[x][2] = 0;
        vis[x] = 1;
    }
    if(op == 2) {//女救 
        if(a[x] != 4 || b[y] || !B[y] || !tag[x][3]) return false;
        B[y] = 0;
        tag[x][3] = 0;
        vis[x] = 1;
        if(a[y] == 3) vis[y] = 0;//女巫救活猎人
    }
    if(op == 3) {//开枪 
        if(a[x] != 3 || !B[x] || B[y] || x == y) return false;
        B[y] = 1;
        vis[x] = 1;
    }
    return true;
}

signed main() {
    FASTIO

    cin >> q >> n;
    rep(i, 1, n) cin >> a[i], tag[i][0] = tag[i][1] = 1;
    while(q--) {
        ++ID;
        memset(vis, 0, sizeof vis);
        memcpy(B, b, sizeof b);
        cnt = flg = 0;
        rep(i, 1, n) tag[i][2] = tag[i][0], tag[i][3] = tag[i][1];
        cin >> m;
        while(m--) {
            int op, x, y;
            cin >> op >> x >> y;
            if(!check(op, x, y)) {
//              cout << '!' << op << ' ' << x << ' ' << y << '\n';
                flg = 1;
                continue;
            }
//          rep(i, 1, n) cout << B[i] << ' ';
//          cout << '\n';
        }
        rep(i, 1, n) if(b[i] == 0 && B[i] == 1 && a[i] == 3 && !vis[i]) flg = 1;//判断是否有死了的猎人没开枪
        if(flg) cout << "Wrong\n";
        else {
            vector<int> p;
            rep(i, 1, n) if(b[i] == 0 && B[i] == 1) p.pb(i);
            cnt = p.size();
            if(!cnt) cout << "Safe\n";
            else {
                cout << cnt << ' ';
                for(auto x : p) cout << x << ' ';
                cout << '\n';
            }
            memcpy(b, B, sizeof b);
            rep(i, 1, n) tag[i][0] = tag[i][2], tag[i][1] = tag[i][3];
        }
    }
}