# 题解:猫萌的敌人 [题目链接](https://vjudge.net/contest/475403#problem/B) ## 分析 极度容易WA的题,特殊情况有点多,由攻击至少1这个点,会产生很多细节坑。具体有哪些细节坑在下面的参考代码的注释里有列出。 在去除掉特殊情况后,重点关注点在枚举的方法上。首先,对于血和防守力的分配上,方案其实是唯一的,因为防守力必然分配为对方攻击力-1,剩下的就是血,这样必然是能支撑最多个回合的方案。所以说,防守力可以算为已知量,那么剩下的两个量,就是在解一个不等式方程组,枚举方法可以有多种,可以枚举回合数,可以直接枚举分配的点数(攻击或血),这样就得到一个时间复杂度为 $O(n)$ 级的算法。 ## 参考代码 ```cpp #include <algorithm> #include <iostream> using namespace std; bool solve(int v, int l, int d, int a) { if (v == 0) // 自己没有点数 return false; a = max(1, a); // 对方攻击至少1 if (v >= l + d + 1) // 全力进攻,留1点血 return true; if (v >= a + l - 1) // 全力防守,血比对方多 return true; if (l <= 1) // 对方支撑不住1次攻击 return true; // 枚举攻击次数 for (int i = 2; i < v; i++) { int at = (l + (i - 1)) / i; // 最少需要的攻击力 int lv = v - (at + d); // 分配攻击力后剩余点数 if (lv >= (a - 1) + i) // 先分配a-1的防守,再判断血够不够 return true; } return false; } int main(int argc, char *argv[]) { int n, k, a, b, c; cin >> n; for (int i = 0; i < n; i++) { cin >> k >> a >> b >> c; bool res = solve(k, a, b, c); cout << (res ? "Yes" : "No") << endl; } return 0; } ```