我正在尝试解决以下问题:https://onlinejudge.org/index.php?option=onlinejudge&Itemid=8&page=show_problem&problem=3693
下面是我的代码:
#include <algorithm>
#include <functional>
#include <iostream>
#include <utility>
#include <vector>
#include <map>
#include <limits>
typedef unsigned int ui;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
ui m,n;
std::cin >> m >> n;
while(m){
std::vector<int> objects(n);
for(auto i = 0u; i < n; i++){
std::cin >> objects[i];
}
//memoizacion
std::map<std::pair<ui, ui>, ui> mem;
std::function<ui(std::pair<ui, ui>)> question = [&](std::pair<ui, ui> set) -> ui {
if(!mem.count(set)){
int inSet = 0;
for(auto i = 0u; i < n; i++){
if(((objects[i] & set.first) == set.first) and (((~objects[i]) & set.second) == set.second))
inSet++;
}
if(inSet <= 1) mem.insert(std::pair<std::pair<ui, ui>, ui>(set, 0));
else {
ui min = std::numeric_limits<ui>::max();
for(auto k = 1u, i = 0u; i < m; i++, k <<= 1){
if(!(k & set.first) and !(k & set.second)){
ui candidate = std::max(question(std::pair<ui,ui>(set.first | k, set.second)),
question(std::pair<ui, ui>(set.first, set.second | k)));
min = min < candidate ? min : candidate;
}
}
mem.insert(std::pair<std::pair<ui, ui>, ui>(set, min + 1));
}
}
return mem.at(set);
};
std::cout << question(std::pair<ui, ui>(0,0)) << "\n";
std::cin >> m >> n;
}
}
当我使用示例输入(在链接中详细说明问题的PDF上)运行此代码时,我的代码解决了前两种情况,然后在第三种情况下进入无限循环
当我用调试器检查它时,我注意到
std::cin >> m >> n;
是导致错误的原因。在阅读完第三种情况后,当它试图再次读时,它什么也不做。一旦达到m = 11,n = 16的情况,m和n不变。就像它被一遍又一遍地调用(因为循环结束的条件是m为0),但它并没有阅读下一个输入,而是停留在那里,对m和n重复相同的值
我真的完全迷路了。我完全不知道这是怎么回事过去的一个小时里我一直在用头撞墙试图解决这个问题
1条答案
按热度按时间9gm1akwq1#
您似乎认为,如果执行
std::cin >> m >> n;
,而cin
没有任何内容可读取,则m
将被设置为0
。但实际上,让我们来看看operator>>
是做什么的:operator>>(std::basic_istream):
1-11)提取可能跳过前面空白的值。该值被存储到给定的引用
value
。此函数的行为类似于FormattedInputFunction。在构造并检查sentry对象(可能跳过前导空格)之后,通过调用
std::num_get::get()
提取一个值。如果FormattedInputFunction无法读取,它会怎么做?
FormattedInputFunction是执行以下操作的流输入函数:
eofbit
或badbit
,则也设置failbit
,如果在此输入流的异常掩码((exceptions() & failbit) != 0
)中启用了failbit
上的异常,则抛出ios_base::failure
。tie()
的输出流(如果适用)ios_base::skipws
标志,则从输入流中提取并丢弃字符,直到以下其中一项变为真:failbit
和eofbit
,并且如果流由于这些位之一上的异常而打开,则抛出ios_base::failure
。sentry::operator bool()
(相当于basic_ios::good
)检查哨兵的状态。false
或sentry的构造函数抛出异常,不发生任何输入重点已添加。如果
std::cin >> m
没有任何可读取的内容,它将不读取m
。因此,在读取失败后,m
仍然是11
,而不是0
,因此while(m)
仍然是true
。关于上述内容的说明:在某些情况下,读取
std::cin >> m
失败会导致m
被设置为0
。如果流中确实有数据可供读取,但此数据无法在std::num_get::get()
步骤中转换为整数:std::num_get::get:
如果转换函数无法转换整个字段,则值
0
存储在v
中。推荐的方法是直接检查读取本身是否成功。因此,不需要在
std::cin >> m >> n;
之后检查m
的值,而是将循环编写为这依赖于
std::istream
有一个operator bool来指示最近的流操作是否成功。这样,所有从cin
读取的失败都会被统一处理。