CSP-J/S 2024 第二轮 入门级 接龙 题解
CSP-J/S 2024 第二轮 入门级 接龙 题解
题目来源:ET题库 - 接龙
题目分析
这是一道关于序列接龙的题目。主要需要考虑以下几点:
- 每个人有自己的词库(整数序列)
- 需要判断是否能在指定轮数内完成接龙
- 接龙时需要考虑数字的连接关系
解题思路
- 首先需要存储每个人的词库
- 对于每个查询,我们需要判断是否能在给定轮数内完成接龙
- 使用动态规划来解决这个问题
代码实现
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
const int MAXK = 1005;
vector<int> wordbank[MAXN]; // 存储每个人的词库
int n, k, q; // n个人,k轮,q个查询
// 判断是否可以完成接龙
bool can_chain(int rounds, int target) {
// dp[i][j] 表示第i轮使用第j个数是否可行
vector<vector<bool>> dp(rounds + 1, vector<bool>(MAXK, false));
// 初始化第一轮
for (int num : wordbank[1]) {
dp[1][num] = true;
}
// 动态规划
for (int i = 1; i < rounds; i++) {
for (int j = 1; j <= k; j++) {
if (!dp[i][j]) continue;
// 尝试接下一个数
for (int next : wordbank[(i % n) + 1]) {
if (next == j) {
dp[i + 1][next] = true;
}
}
}
}
// 检查最后一轮是否能达到目标
return dp[rounds][target];
}
int main() {
freopen("chain.in", "r", stdin);
freopen("chain.out", "w", stdout);
// 读入数据
cin >> n >> k >> q;
for (int i = 1; i <= n; i++) {
int li;
cin >> li;
wordbank[i].resize(li);
for (int j = 0; j < li; j++) {
cin >> wordbank[i][j];
}
}
// 处理查询
while (q--) {
int r, c;
cin >> r >> c;
cout << (can_chain(r, c) ? 1 : 0) << endl;
}
return 0;
}
代码解释
1. 数据结构
vector<int> wordbank[MAXN]; // 存储每个人的词库
使用vector数组存储每个人的词库,方便访问和管理。
2. 动态规划部分
vector<vector<bool>> dp(rounds + 1, vector<bool>(MAXK, false));
dp[i][j]
表示第i轮使用第j个数是否可行- 通过两层循环来填充dp数组
- 对于每个可行状态,尝试接下一个数
3. 查询处理
while (q--) {
int r, c;
cin >> r >> c;
cout << (can_chain(r, c) ? 1 : 0) << endl;
}
对每个查询调用can_chain函数判断是否可行。
时间复杂度分析
- 预处理:O(n)
- 每次查询:O(rounds * k * max_wordbank_size)
- 总体复杂度:O(q * k * n * max_wordbank_size)
注意事项
- 文件输入输出
freopen("chain.in", "r", stdin); freopen("chain.out", "w", stdout);
- 边界条件处理
- 注意检查rounds和target的合法性
- 考虑特殊情况(如第一轮)
总结
这道题是一个典型的动态规划问题,关键在于:
- 正确定义状态
- 找到状态转移方程
- 合理处理边界条件
希望这个题解对你有帮助!如果有任何问题,欢迎在评论区讨论。