1 条题解
-
0
田忌赛马问题题解
一、题目分析
题目要求计算田忌通过合理安排马匹顺序,在与齐王的赛马中能获得的最大收益。关键条件:
- 每匹马必须参赛且仅参赛一次;
- 速度快的马必定战胜速度慢的马,平局不得分;
- 每胜一局得200银元,每败一局扣200银元。
二、算法思路
- 贪心策略:
- 比较双方最快的马:
- 若田忌最快的马 > 齐王最快的马,用田忌最快的马对阵齐王最快的马;
- 若田忌最快的马 < 齐王最快的马,用田忌最慢的马对阵齐王最快的马;
- 若双方最快的马速度相同,比较双方最慢的马:
- 若田忌最慢的马 > 齐王最慢的马,用田忌最慢的马对阵齐王最慢的马;
- 否则,用田忌最慢的马对阵齐王最快的马。
- 比较双方最快的马:
三、代码实现
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1000+10; int v1[maxn], v2[maxn]; // 田忌和齐王的马速 int main() { int n; while(scanf("%d", &n) == 1 && n) { for(int i = 0; i < n; i++) scanf("%d", &v1[i]); for(int i = 0; i < n; i++) scanf("%d", &v2[i]); // 排序:从小到大 sort(v1, v1 + n); sort(v2, v2 + n); int ans = 0; // 最终得分 int cnt = n; // 剩余比赛局数 int max1 = n - 1, max2 = n - 1; // 指向最快的马 int min1 = 0, min2 = 0; // 指向最慢的马 while(cnt--) { if(v1[max1] > v2[max2]) { // 田忌最快马 > 齐王最快马 ans += 200; max1--; max2--; } else if(v1[max1] < v2[max2]) { // 田忌最快马 < 齐王最快马 ans -= 200; min1++; max2--; } else { // 双方最快马速度相同 if(v1[min1] > v2[min2]) { // 田忌最慢马 > 齐王最慢马 ans += 200; min1++; min2++; } else { // 否则用田忌最慢马对阵齐王最快马 if(v1[min1] < v2[max2]) ans -= 200; // 若田忌最慢马 < 齐王最快马,扣分 min1++; max2--; } } } printf("%d\n", ans); } return 0; }
四、代码解释
-
输入处理与排序:
- 读取双方马匹速度并排序,以便快速获取最快和最慢的马。
-
贪心策略实现:
- 使用双指针
max1
、min1
指向田忌的最快和最慢马; - 使用双指针
max2
、min2
指向齐王的最快和最慢马; - 根据马匹速度比较结果,调整指针位置并更新得分。
- 使用双指针
-
核心逻辑:
- 优先用田忌最快的马击败齐王最快的马;
- 若无法取胜,则用田忌最慢的马消耗齐王最快的马;
- 当最快马速度相同时,比较最慢马,确保局部最优。
五、示例解析
输入样例1:
3 92 83 71 95 87 74
- 排序后:
- 田忌:71, 83, 92
- 齐王:74, 87, 95
- 比赛过程:
- 田忌最快马92 < 齐王最快马95,用田忌最慢马71对阵齐王最快马95,输一局;
- 剩余马匹:田忌83, 92,齐王74, 87;
- 田忌最快马92 > 齐王最快马87,用92对阵87,赢一局;
- 剩余马匹:田忌83,齐王74;
- 田忌最快马83 > 齐王最快马74,用83对阵74,赢一局;
- 总得分:200银元。
六、复杂度分析
- 时间复杂度:O(n log n),主要来自排序操作;
- 空间复杂度:O(n),存储马匹速度。
七、关键技巧
- 贪心策略:通过比较双方最快和最慢的马,做出最优选择;
- 双指针优化:利用排序后的数组,通过双指针快速定位极值元素;
- 平局处理:当最快马速度相同时,进一步比较最慢马,确保利益最大化。
- 1
信息
- ID
- 1289
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者