day-1

bfs 保存路径

https://codeforces.com/contest/1534/problem/E

本质是:n个硬币,每次可以将k个硬币翻面,问最少需要多少次就能将所有硬币从正面翻转到反面
需要bfs搜索出最优路径并且需要记录前驱。


const int maxn = 1e6 + 7;
const int mod = 1e9 + 7;
 
int n, t, k, dis[maxn], pre[maxn], col[maxn];
stack<int> path;
void bfs()
{
    for (int i = 0; i <= n; i++)
        dis[i] = mod, col[i] = 0;
    queue<int> que;
    pre[0] = -1, que.push(0), dis[0] = 0;
    while (que.size()) {
        int now = que.front();
        que.pop();
        for (int x = 0; x <= k; x++) {
            int to = now + k - 2 * x;
            if (to > n || to < 0 || x > now || k - x > n - now)
                continue;
            if (dis[to] > dis[now] + 1)
                dis[to] = dis[now] + 1, pre[to] = now, que.push(to);
        }
    }
    while (path.size())
        path.pop();
    for (int c = n; c != -1; c = pre[c]) {
        if (pre[c] == -1)
            continue;
        path.push(c - pre[c]);
    }
}
void solve()
{
    if (dis[n] == mod) {
        cout << "-1" << endl;
        return;
    }
    int ans = 0, as;
    while (path.size()) {
        int c = path.top();
        path.pop();
        cout << "? ";
        int zcnt = k - c >> 1, ocnt = k - zcnt;
        for (int i = 1, o = 0, c = 0; i <= n; i++) {
            if (o < ocnt && col[i] == 0) {
                col[i] = 1, o++;
                cout << i << " ";
            } else if (c < zcnt && col[i] == 1) {
                col[i] = 0, c++;
                cout << i << " ";
            }
        }
        cout << endl;
        cout.flush();
        cin >> as;
        ans ^= as;
    }
    cout << "! " << ans << endl;
}
int main()
{
    // cin >> t;
    // while (t--) {
        cin >> n >> k;
        bfs();
        solve();
    // }
}

7.25 重写

注意枚举翻到正面个数的范围 path要明白是啥意思...




const int maxn = 1e4 + 7;

int n, k;

int dis[maxn], path[maxn];

void bfs() {
    dis[0] = 0;
    queue<int> que;
    que.push(0);
    while (que.size()) {
        int tp = que.front();
        que.pop();
        for (int c = 0; c <= k; c++) {
            int nx = tp + c - (k - c);
            if (nx <= 0 || nx > n || k - c > tp || c > n - tp)
                continue;
            if (dis[nx] > dis[tp] + 1) {
                dis[nx] = dis[tp] + 1;
                path[nx] = c;
                que.push(nx);
            }
        }
    }
}

void solve() {
    memset(dis, 0x3f, sizeof dis);
    cin >> n >> k;
    bfs();

    if (dis[n] > 1e5) {
        cout << -1 << endl;
        return;
    }
    vector<int> vec;

    int nx = n;
    while (nx)
        vec.push_back(path[nx]), nx = nx - (path[nx] - (k - path[nx]));
    reverse(vec.begin(), vec.end());
    queue<int> good, bad, tp, tp_;
    for (int i = 1; i <= n; ++i)
        bad.push(i);
    int ans = 0;

    for (int i = 0, c; i < vec.size(); i++) {
        cout << "? ";
        c = vec[i];

        for (int j = 0; j < c; ++j)
            tp.push(bad.front()), bad.pop();
        for (int j = 0; j < k - c; j++)
            tp_.push(good.front()), good.pop();

        while (tp.size())
            cout << tp.front() << " ", good.push(tp.front()), tp.pop();
        while (tp_.size())
            cout << tp_.front() << " ", bad.push(tp_.front()), tp_.pop();
        cout << endl;
        cin >> c;
        ans ^= c;
    }
    cout << "! " << ans << endl;
}

配置manjaro:
1.vmware
2.vscode gdb...
3.fictx5

posted @ 2021-07-13 18:44  naymi  阅读(72)  评论(0)    收藏  举报