田忌赛马 贪心 注意细节

http://poj.org/problem?id=2287

田忌赛马

题意:给田忌 和 国王 各自n匹马

比赛n轮 每匹马只能比一场  赢的一方得200 平得0

田忌最多赢多少

 

思路

贪心:局部最优------》》全局最优

先排序 大到小

然后ti  ki 分别指向田忌 国王当前(即还没比)最大速度那匹马

tj  kj   各自。。。。最小速度

 

1)田最快 > 国王最快 -----------田肯定赢  

注意:是否拿田最快  打  国王最快    我当时认为最贪心应该看看后面还有没有也能 打过  国王最快的  有就拿那匹

分析:田  A B C D

         国王 K F J

现在会不会存在一种情况  B能打过K 但不能打过F  而A能打过F? 如果存在那就证明我上面的猜想正确 不能直接用田最快 打 王最快

A >= B   K>=F   如果B打过K 必然B就能打过F 所以不存在

所以答案应该 田最快 打 王最快 

 

2)田最快 < 国王最快 -----------田肯定输

         直接拿田当前最慢的 和  王最快的比

3)田最快 ==国王最快

       3.1)  如果田最慢  > 王最慢  ----田赢

                    田最慢  打 王最慢

        3.2)  如果田最慢  == 王最慢  ----田可能输 可能平

                既然赢不了 那就用田最慢  耗掉 王的最快吧

                输:田最慢   < 王最快

                平:田最慢   == 王最快(可能当前只剩1匹 最快最慢都是一匹 那不就有可能相等了)

#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<functional>

using namespace std;
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define mem(a, b) memset(a, b, sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
//#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);

const int maxn = 1000 + 100;
int tian[maxn], king[maxn];
int cmp(int a, int b){
	return a > b;
}

int main(){
	int n;
	while (~scanf("%d", &n) && n){
		for (int i = 1; i <= n; ++i) cin >> tian[i];
		for (int i = 1; i <= n; ++i) cin >> king[i];

		sort(tian + 1, tian + n + 1, cmp);
		sort(king + 1, king + n + 1, cmp);

		int ans = 0;
		int cnt = 0;
		int ti, tj, ki, kj;
		ti = ki = 1, tj = kj = n;
		while (/*ti <= tj*/cnt < n){
			cnt++;
			//田最快  > 王最快
			//田赢200
			if (tian[ti] > king[ki]){
				ans += 200;
				ti++, ki++;
			}
			//田最快  == 王最快
			else if (tian[ti] == king[ki]){
				//田最慢  > 王最慢
				//田赢200
				if (tian[tj] > king[kj]){
					ans += 200;
					tj--, kj--;
				}
				//田最慢  <= 王最慢  田慢 打  王快 
				//田肯定输
				else{
					//为什么是田最慢 < 王最快  
					if (tian[tj] < king[ki])
						ans -= 200;
					tj--, ki++;
				}

				////田最慢  < 王最慢  田慢 打  王快  
				////田输
				//else if (tian[tj] < king[kj]){
				//	tj--,ki++;
				//	ans -= 200;
				//}
				////平局
				//else {
				//	tj--,ki++;
				//}
			}
			//田快  < 王快  拿田慢 比  王快
			//田输
			else{
				tj--, ki++;
				ans -= 200;
			}
		}

		printf("%d\n", ans);
	}
}

 

<think>好的,我需要帮助用户找到田忌赛马问题在C语言中使用贪心算法的实现。首先,我得回忆一下田忌赛马的基本情况和贪心算法的应用方式。 田忌赛马的故事中,田忌通过合理安排马的出场顺序,以弱胜强。贪心算法在这里通常用于每一步选择最优策略,比如用最差的马消耗对方最强的,或者用最好的马尽可能赢比赛。用户需要的是C语言的实现,所以得考虑如何将这种策略转化为代码。 接下来,我需要确保解决方案符合贪心算法的核心步骤。通常包括:排序双方的马匹,然后比较马匹的速度,选择最优的对阵方式。这里可能会有不同的策略,比如田忌的最快马如果比齐王的最快马快,就直接赢;否则用最慢的马去消耗对方的最快马,以保存实力。 然后,我得考虑C语言的具体实现。需要将双方的马排序,然后使用双指针来遍历比较。例如,使用两个数组分别代表田忌和齐王的马,排序后,用两个指针分别指向当前最快和最慢的马,根据情况决定如何匹配。 还需要注意代码的结构,比如输入处理、排序函数的使用,以及胜负条件的判断。例如,在C语言中可以使用qsort函数来排序数组,然后使用while循环和指针移动来遍历数组。 同时,我需要检查代码的正确性,比如排序是否正确,指针移动是否合理,以及得分计算是否符合逻辑。例如,当田忌的慢马输给齐王的快马时,是否正确地减少了损失,或者当平局时如何处理。 可能遇到的问题包括如何处理平局的情况,是否应该让平局的情况保留到后续比较,或者直接跳过。不同的策略可能导致不同的结果,需要确保代码逻辑与所选贪心策略一致。 最后,我需要验证代码的正确性,比如通过示例输入,如田忌的马速度为[3, 5, 7],齐王的为[2, 6, 8],预期输出应为1,即田忌赢一场,输一场,平一场,总分200。这时候代码是否能正确计算得分。 另外,用户可能需要相关的问题,比如贪心策略的选择理由、时间复杂度分析、优化方法等,需要准备这些问题以供用户进一步学习。</think>### 田忌赛马贪心算法C语言实现 #### 问题分析 田忌赛马问题要求通过合理安排马匹对阵顺序,最大化比赛得分。贪心策略核心思想: 1. 用最差的马消耗对方最强的马(保存实力) 2. 用最好的马尽可能赢得比赛 #### 算法步骤 1. 将田忌和齐王的马速分别升序排序 2. 设置四个指针比较最优/最劣马匹 3. 分三种情况处理最优对阵策略 #### C语言实现代码 ```c #include <stdio.h> #include <stdlib.h> int compare(const void *a, const void *b) { return *(int*)a - *(int*)b; } int tianji_race(int tian[], int qi[], int n) { qsort(tian, n, sizeof(int), compare); qsort(qi, n, sizeof(int), compare); int t_slow = 0, t_fast = n-1; int q_slow = 0, q_fast = n-1; int score = 0; while (t_slow <= t_fast) { if (tian[t_fast] > qi[q_fast]) { // 田忌快马能赢 score += 200; t_fast--; q_fast--; } else if (tian[t_slow] > qi[q_slow]) { // 田忌慢马能赢 score += 200; t_slow++; q_slow++; } else { // 用最差马消耗对方最优马 if (tian[t_slow] < qi[q_fast]) score -= 200; t_slow++; q_fast--; } } return score; } int main() { int n = 3; int tian[] = {3, 5, 7}; int qi[] = {2, 6, 8}; printf("最终得分: %d\n", tianji_race(tian, qi, n)); // 输出200 return 0; } ``` #### 代码解析 1. **排序处理**:使用`qsort`对双方马匹升序排列,时间复杂度$O(n \log n)$ 2. **双指针策略**: - `t_fast`和`q_fast`指向当前最快马 - `t_slow`和`q_slow`指向当前最慢马 3. **核心逻辑**: - 优先用快马赢快马(当田忌快马更强时) - 次选用慢马赢慢马(当田忌慢马更强时) - 最后用最差马消耗对方最优马(减少损失) #### 性能指标 - 时间复杂度:$O(n \log n)$(主要来自排序过程) - 空间复杂度:$O(1)$(原地操作) [^1]: 该实现参考了贪心算法在最优匹配问题中的通用解法思路
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值