题目思路
有点类似于田忌赛马
的问题,可以想到用贪心的最优策略
第一解
求SSS最小受罚次数
MMM可以按任意顺序拿出数字,枚举遍历SSS中的每一个数,对于每一个数 aaa 只有两种情况:
- W中有还未用且 ≥ a 的数,此时选
满足条件
的最小的数 - W中的数都 < a 的数, 此时选
未用
的数中最小的数
代码实现
for (int i = 1; i <= len; i++) { bool ok = 0; for (int j = 1; j <= len; j++) if (a[j] >= b[i] and !used[j]) {ok = 1, used[j] = 1; break;} if (!ok) for (int j = 1; j <= len; j++) if (!used[j]) {used[j] = 1, ans1++; break;} }
第二解
求MMM最大受罚数
做法相似,枚举遍历SSS中的每一个数,对于每一个数aaa只有两种情况:
- W中有还未用且 > a 的数,此时选
满足条件
的最小的数 - W中的数都 ≤ a 的数, 此时选
未用
的数中最小的数
代码实现
for (int i = 1; i <= len; i++) { bool ok = 0; for (int j = 1; j <= len; j++) if (a[j] > b[i] and !used[j]) {ok = 1, used[j] = 1, ans2++; break;} if (!ok) for (int j = 1; j <= len; j++) if (!used[j]) {used[j] = 1; break;} }
完整代码
#include <bits/stdc++.h> using namespace std; char a[1005], b[1005]; bool used[1005]; //used记录是否被用 int len, ans1, ans2; //ans1记录 M 最少受罚次数, ans2记录 S 最多受罚次数 int main() { scanf ("%d %s %s", &len, b + 1, a + 1); sort (a + 1, a + len + 1); //第一问: for (int i = 1; i <= len; i++) { bool ok = 0; //ok记录是否有满足要求的数 for (int j = 1; j <= len; j++) if (a[j] >= b[i] and !used[j]) {ok = 1, used[j] = 1; break;} //如果没有则选最小的数 if (!ok) for (int j = 1; j <= len; j++) if (!used[j]) {used[j] = 1, ans1++; break;} //此时受罚次数 +1; } memset (used, 0, sizeof (used)); //清零used数组 //第二问: for (int i = 1; i <= len; i++) { bool ok = 0; //ok记录是否有满足要求的数 for (int j = 1; j <= len; j++) if (a[j] > b[i] and !used[j]) {ok = 1, used[j] = 1, ans2++; break;} //如果没有则选最小的数 if (!ok) for (int j = 1; j <= len; j++) if (!used[j]) {used[j] = 1; break;} //此时不受罚次数 +1; } printf ("%d\n%d", ans1, ans2); return 0; }