UVa LA 3266 - Tian Ji -- The Horse Racing 贪心,不只处理一端,也处理另一端以理清局面 难度: 2

题目

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1267


题意

田忌赛马,问最多能赢到多少钱?每局200元

 

思路

明显,把田忌的赛马排列一下,从速度高到低,齐王的也从高到低排列,当前田忌最高的赛马无法处理齐王最高的赛马,则换成田忌最慢的赛马去碰瓷。

难在如何处理平局-也就是速度相同的赛马。

有的时候本可以平局,但是最好先认输一局-换用目前最慢的赛马去碰瓷一下,然后当前这匹赛马与接下来比它弱的赛马比试,这样做胜一局负一局,收益为0,与直接平局是相同的。但是优点在于额外用田忌的驽马解决了一匹齐王的好马。

那么,何时直接平局,何时解决额外的马呢?

不妨看看目前的驽马,如果当前自己最慢的马还能解决齐王的最慢马,那么优先让这个对局发生。直到自己最慢的马无法解决齐王最慢的马,此时用这匹驽马来额外解决齐王的快马。

 

感想

1. 一开始只想到越高越好,从高到低直接处理,没有考虑到当前自己最慢的马还能解决齐王的最慢马这种情况,导致没法选择何时应该主动放弃平局。

2. 之后用了DP,太慢

3. 不只处理一端,也处理另一端以理清局面

 

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1e3 + 3;
typedef pair<int, int> Pair;
int a[MAXN];
int b[MAXN];
int n;
int main() {
	int T;
	//scanf("%d", &T);
	freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\input.txt", "r", stdin);
	//freopen("C:\\Users\\Iris\\source\\repos\\ACM\\ACM\\output.txt", "w", stdout);
	for (int ti = 1; scanf("%d", &n) == 1 && n; ti++) {
		for (int i = 0; i < n; i++) {
			scanf("%d", a + i);
		}
		sort(a, a + n);
		for (int i = 0; i < n; i++) {
			scanf("%d", b + i);
		}
		sort(b, b + n);
		int ans = 0;
		for (int ai = n - 1, astart = 0, bi = n - 1, bstart = 0; ai >= astart && bi >= bstart; ) {
			while (bi >= 0 && a[ai] < b[bi]) {
				bi--;
				ans--;
				astart++;
			}
			if (bi >= 0) {
				if (a[ai] > b[bi]) {
					ans++;
					bi--;
					ai--;
				}
				else {
					while (ai >= astart && bi >= bstart && a[astart] > b[bstart]) {
						ans++;
						astart++;
						bstart++;
					}
					if (ai >= astart && bi >= bstart && a[astart] < b[bi]) {
						astart++;
						bi--;
						ans--;
					}
					else {
						break;
					}
				}
			}
		}
		printf("%d\n", ans * 200);
	}
	return 0;
}

  

posted @ 2019-04-09 09:38  雪溯  阅读(156)  评论(0编辑  收藏  举报