1. 题目背景与问题解析
P3005 [USACO10DEC] The Trough Game S 是美国计算机奥林匹克竞赛(USACO)2010年12月月赛银组的一道经典题目。这道题考察选手对位运算和状态压缩的理解应用能力,属于典型的"猜数字"类逻辑推理问题。
题目描述一个有趣的农场游戏:有M个长度为N的二进制串(每个串表示一个饲料槽的开关状态),每个串对应一个数字表示该状态下有多少头奶牛会进食。玩家需要通过这些线索,找出唯一满足所有条件的初始二进制串(即饲料槽的正确开关组合)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心算法思路
2.1 暴力枚举法
最直观的解法是枚举所有可能的N位二进制串(共2^N种可能),对每个候选串检查是否满足所有M个条件。具体步骤:
- 生成所有N位二进制数(从0到2^N-1)
- 对每个数转换为二进制串表示
- 计算该串与每个给定串的按位与结果中1的个数
- 验证是否与对应数字完全匹配
- 记录满足所有条件的解
时间复杂度:O(M*2^N),当N<=20时可行(约百万次操作)
2.2 位运算优化
利用位运算特性可以显著提升效率:
cpp复制// 示例核心判断逻辑
bool check(int candidate) {
for(int i=0; i<M; ++i) {
if(__builtin_popcount(candidate & masks[i]) != counts[i])
return false;
}
return true;
}
其中masks数组存储将每个二进制串转换成的整数形式,counts数组存储对应的数字。
3. 关键实现细节
3.1 输入处理技巧
输入格式为:
code复制N M
二进制串1 数字1
...
二进制串M 数字M
建议的读取方式:
cpp复制vector<int> masks(M);
vector<int> counts(M);
for(int i=0; i<M; ++i) {
string s; int cnt;
cin >> s >> cnt;
masks[i] = stoi(s, 0, 2); // 二进制字符串转整数
counts[i]
