专栏文章

题解:P8838 [传智杯 #3 决赛] 面试

P8838题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miof1xic
此快照首次捕获于
2025/12/02 18:09
3 个月前
此快照最后确认于
2025/12/02 18:09
3 个月前
查看原文
一道搜索题。

思路分析

用 dfs 暴力枚举即可,由于 n,k6n,k \le 6,所以解法不会超时。
dfs 每一个指令,匹配每一个服务器,只要找到第一种解,就是字典序最小的,因为每一层遍历都是从小到大的。
1. 确定递归边界:
kk 个指令都匹配完后,就找到了正解。
CPP
if (x == k + 1) { // 指令都匹配完了
    for (int i = 1; i <= n; i++) cout << ans[i] << " "; // 输出正解序列
    exit(0); // 结束程序
}
2. 循环匹配服务器:
for 循环给当前指令匹配每一个服务器。
只要当前服务器 aia_i 能处理当前指令 bxb_xaibxa_i \ge b_x)并且当前服务器没有被其他指令匹配过,就可以匹配。
CPP
for (int i = 1; i <= n; i++) // 寻找合适的服务器
    if (!vis[i] && a[i] >= b[x]) { // 满足匹配条件
        vis[i] = true; // 标记为匹配过
        ans[x] = i; // 记录答案
        dfs(x + 1); // dfs 下一层
        vis[i] = false; // 回溯
    }
最后判无解。只要在 dfs 时没找到正解,就是无解,输出 -1

完整 AC 代码

CPP
#include<iostream>
using namespace std;
int n, k;
int a[10], b[10];
int ans[10], vis[10];
void dfs(int x) {
    if (x == k + 1) {
        for (int i = 1; i <= n; i++) cout << ans[i] << " ";
        exit(0);
    }
    for (int i = 1; i <= n; i++)
        if (!vis[i] && a[i] >= b[x]) {
            vis[i] = true;
            ans[x] = i;
            dfs(x + 1);
            vis[i] = false;
        }
}
int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= k; i++) cin >> b[i];
    dfs(1); // 暴力枚举
    cout << -1; // 无解
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...