中南大学OJ 2012年8月月赛,H题,Happy watering(题目链接)。
Problem H: Happy watering
Description
GBQC国的小明家里有N棵树,每天小明都会给其中一棵树浇水,每次浇水后,树都会长高一些,但由于树的品种不同,每次增长的高度也有所区别。
为了使这N棵树看起来整洁、美观,小明希望最高的树和最低的树的高度差越小越好。现在小明想知道,如果至多浇K次水,最高的树和最低的树的高度差最小为多少?
Input
输入包含多组测试数据。
对于每组测试数据,第一行包含两个正整数N(2 ≤ N ≤ 105)、K(1 ≤ K ≤ 105),含义同上。接下来一共有N行,每行有两个正整数h(1 ≤ h ≤ 103)、d(1 ≤ d ≤ 103),分别描述了这N棵树的初始高度,以及每次浇水后这棵树增长的高度。
Output
对于每组测试数据,用一行输出一个整数表示如果小明至多浇K次水,最高的树和最低的树的高度差最小为多少。
Sample Input
2 1
7 2
10 3
2 4
7 2
10 3
2 3
7 8
10 9
Sample Output
1
0
3
Hint
由于数据量较大,推荐使用scanf和printf。
解题思路:使用C++中的STL的multiset来储存树木的自身高度和每次浇水长高的高度。按照自身高度排序。每次取出最矮的,浇一次水。浇水同时,循环打擂求最小极差。求极差的方法:每次都把最高的树(即multiset中的最后一个元素)的高度,减去最矮的树(即multiset中的第一个元素)的高度,即为极差。最终输出最小极差即可。
C++语言源代码如下:
#include <cstdio> #include <cstdlib> #include <set> #include <climits> using namespace std; typedef int COUNT; class tree_property { public: int height; int grown_per_water; bool operator<(const tree_property & tree ) const { return height < tree.height; } }; void read_data( multiset <tree_property> & ordered_trees, const int tree_count ) { tree_property tree; for ( COUNT i = 0 ; i < tree_count ; i ++ ) { scanf( "%d%d", &(tree.height), &(tree.grown_per_water) ); ordered_trees.insert(tree); } } int water_tree( multiset <tree_property> & trees, const int tree_count, const int max_water ) { int range, min_range; tree_property shortest_tree; multiset <tree_property>::iterator shortest_tree_iterator; multiset <tree_property>::iterator tallest_tree_iterator; shortest_tree_iterator = trees.begin(); tallest_tree_iterator = trees.end(); tallest_tree_iterator --; min_range = range = tallest_tree_iterator->height - shortest_tree_iterator->height; for ( COUNT i = 0 ; i < max_water ; i ++ ) { shortest_tree_iterator = trees.begin(); shortest_tree = (*shortest_tree_iterator); trees.erase( shortest_tree_iterator ); shortest_tree.height += shortest_tree.grown_per_water; trees.insert( shortest_tree ); shortest_tree_iterator = trees.begin(); tallest_tree_iterator = trees.end(); tallest_tree_iterator --; range = tallest_tree_iterator->height - shortest_tree_iterator->height; if ( range < min_range ) min_range = range; } return min_range; } void test_case( const int tree_count, const int max_water ) { multiset <tree_property> trees; read_data( trees, tree_count ); printf( "%d\n" , water_tree( trees, tree_count, max_water ) ); } int main (void) { int tree_count, max_water; while ( scanf( "%d%d", &tree_count, &max_water ) != EOF ) { test_case( tree_count, max_water ); } return EXIT_SUCCESS; }