Codeforces 1842B题测试点2WA,请求代码错误排查帮助
题目描述
Tenzing收到3n本书,分成3个栈,每个栈n本,每本书有非负整数难度值。初始知识为0,每次可选择非空栈读栈顶书,知识变为当前值与书难度的位或(|),可随时停止。问能否让知识等于x?
输入:
- 多组测试用例
- 每组首行输入n和x
- 随后三行各n个数,分别为三个栈的书(从上到下)
输出:能达成目标则输出Yes,否则输出No
问题情况
比赛提交的代码在测试点2出现Wrong Answer,无法查看具体测试用例,自行测试未发现问题,请求排查错误。代码如下:
#include <iostream> using namespace std; int main() { int t; cin>>t; while(t--) { int n,i,p1=0,p2=0,p3=0; long long x,knowledge=0; cin>>n>>x; long long a[n],b[n],c[n]; for(i=0;i<n;i++) cin>>a[i]; for(i=0;i<n;i++) cin>>b[i]; for(i=0;i<n;i++) cin>>c[i]; while(p1<n||p2<n||p3<n) { if(knowledge==x) { cout<<"YES"<<endl; break; } if(knowledge > x) { cout<<"NO"<<endl; break; } if(p1<n && (a[p1]|x)==x) knowledge |= a[p1++]; else if(p2<n && (b[p2]|x)==x) knowledge |= b[p2++]; else if(p3<n && (c[p3]|x)==x) knowledge |= c[p3++]; else { cout<<"NO"<<endl; break; } } if(p1>=n&&p2>=n&&p3>=n) cout<<"NO"<<endl; } return 0; }
错误分析
1. 贪心策略逻辑错误
代码采用固定顺序(栈a→栈b→栈c)选择符合条件的书,但位或操作的顺序会影响最终结果。例如:某本书单独满足(book | x) == x,但先读取它可能阻塞后续其他栈的书凑出x的路径,而换一种读取顺序就能达成目标。固定顺序无法覆盖所有可能的有效组合。
2. 非标准数组定义
C++标准不支持用变量n定义变长数组long long a[n],这属于编译器扩展语法,可能导致未定义行为(如内存分配错误),应改用vector<long long>动态分配内存。
3. 输出逻辑冗余且错误
当循环中已经达成knowledge == x并break后,后续的if(p1>=n&&p2>=n&&p3>=n)会再次输出NO,导致重复输出结果。
4. 多余的判断逻辑
位或操作只会将二进制位从0置为1,不会反向修改,因此knowledge永远不会大于x(只要所有选的书都满足(book | x) == x),if(knowledge > x)的判断完全多余。
修正方案
核心思路
枚举所有3个栈的访问顺序(共6种排列),对每种顺序模拟读取过程,只要存在一种顺序能让知识达到x,就输出YES。
修正代码
#include <iostream> #include <vector> using namespace std; // 模拟某一种栈访问顺序的读取过程 bool simulate(int n, long long x, vector<long long>& a, vector<long long>& b, vector<long long>& c, int order[]) { long long knowledge = 0; int ptr[3] = {0, 0, 0}; while (ptr[0] < n || ptr[1] < n || ptr[2] < n) { if (knowledge == x) return true; bool found = false; // 按指定顺序尝试读取栈顶书 for (int i = 0; i < 3; ++i) { int idx = order[i]; vector<long long>& stack = (idx == 0) ? a : (idx == 1) ? b : c; if (ptr[idx] < n && (stack[ptr[idx]] | x) == x) { knowledge |= stack[ptr[idx]]; ptr[idx]++; found = true; break; } } if (!found) break; // 没有可读取的有效书,终止模拟 } return knowledge == x; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int n; long long x; cin >> n >> x; vector<long long> a(n), b(n), c(n); for (int i = 0; i < n; ++i) cin >> a[i]; for (int i = 0; i < n; ++i) cin >> b[i]; for (int i = 0; i < n; ++i) cin >> c[i]; bool can_reach = false; // 枚举所有6种栈访问顺序 int orders[6][3] = {{0,1,2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0}}; for (int i = 0; i < 6; ++i) { if (simulate(n, x, a, b, c, orders[i])) { can_reach = true; break; } } cout << (can_reach ? "YES" : "NO") << '\n'; } return 0; }
内容的提问来源于stack exchange,提问作者Ishan Joshi
相关产品推荐
相关产品推荐

