POJ 3927 Priest John's Busiest Day

来源:互联网 发布:会跳舞的向日葵知乎 编辑:程序博客网 时间:2024/04/28 23:08

题目大意:

        今天是神父John最忙的一天,镇里有N(1 ≤ N ≤ 100,000)对新婚夫妇要举办婚礼,每场婚礼都需要牧师当场为两位新人祝福祈祷,每对新人都计划好了各自婚礼的开始时间Si和结束时间Ti(Si、Ti都为int型自然整数),当地有一个习俗,那就是牧师祝福的时间必须超过整个婚礼时间的一半,并且:

        1. 牧师不能同时为两场婚礼祝福;

        2. 牧师到场和离开的时间都是整数;

        3. 牧师在结束一场祝福的瞬间就能到下一场进行祝福;

        求一个牧师祝福的合理顺序,使得所有新人的婚礼都能被牧师完整地祝福。

        现有多个测例,每个测例中都给出N,以及N长婚礼的Si和Ti,现要求你对每个测例进行判断,计算牧师能否将所有婚礼的完整祝福一遍,如果能输出YES,否则输出NO,每个测例占一行,输入以N = 0结束。

题目链接

注释代码:

/*                                              * Problem ID : POJ 3927 Priest John's Busiest Day   * Author     : Lirx.t.Una                                              * Language   : C++                             * Run Time   : 344 ms                                              * Run Memory : 1692 KB                                             */#include <algorithm>#include <iostream>#include <cstdio>//maximum number of couples//婚礼的最大数量(最多有多少对夫妇)#defineMAXCPN100000using namespace std;structWed {//wedding,婚礼ints, t;//start,terminal,开始时间和结束时间intas, at;//appear start and terminal,牧师必须出场的时间段voidinit(void) {scanf("%d%d", &s, &t);//牧师祝福时间必须超过婚礼时间的一半//因此可以由此计算出牧师最早结束祝福的时间at//和牧师最早的出场时间as//则[as, at]为牧师无论如何都得出场的时间if ( ( t - s ) % 2 ) {//奇数情况as = s + ( ( t - s - 1 ) >> 1 );at = as + 1;}else {//偶数情况as = s + ( ( t - s ) >> 1 ) - 1;at = as + 2;}}intmintv(void) {//minimum interval time//牧师至少祝福多长时间//即婚礼时间一半+1//用于贪心选择return ( t - s + 2 ) >> 1;}booloperator<(const Wed &oth)//将婚礼按照牧师最晚出席时间从小到大排序const {//如果有相等的情况则再按照最早离开时间从小到大排序,用于贪心选择return as < oth.as || ( as == oth.as && at < oth.at );}};Wedw[MAXCPN];//wedding,婚礼boolcan_hold_all(int n) {//判断牧师是否能正常祝福完所有新婚夫妇//即贪心选择的核心算法,在这之前必须先对婚礼进行sort排序intcur_s, cur_t;//当前婚礼牧师的出场时间和牧师的离开时间intprv_t;//上一场婚礼牧师的离开时间inti;prv_t = (*w).mintv();//将prv_t初始化为第一场婚礼(下标为0)的最早结束时间//也就是说一切都进行地越早越好,可以方便为后续的祝福腾出更多时间//这就是贪心算法的核心!!!for ( i = 1; i < n; i++ ) {//从1开始往后检测cur_s = w[i].s;if ( cur_s < prv_t ) cur_s = prv_t;//如果当前婚礼开始时牧师上一场还没结束//则必须等牧师上一场结束后才能开始当前婚礼的祝福cur_t = cur_s + w[i].mintv();//让牧师尽早结束当前婚礼的祝福if ( cur_t > w[i].t ) return false;//如果当前婚礼祝福完时已经超出夫妻预设的结束时间//则牧师不能完成当前婚礼的祝福,所以失败退出prv_t = cur_t;//否则就是合理结束了,更新prv_v即可}return true;//一切正常,成功退出}intmain() {intn;//婚礼数inti;//计数变量while ( scanf("%d", &n), n ) {for ( i = 0; i < n; i++ ) w[i].init();sort(w, w + n);if ( can_hold_all(n) ) puts("YES");else puts("NO");}return 0;}

无注释代码:

#include <algorithm>#include <iostream>#include <cstdio>#defineMAXCPN100000using namespace std;structWed {ints, t;intas, at;voidinit(void) {scanf("%d%d", &s, &t);if ( ( t - s ) % 2 ) {as = s + ( ( t - s - 1 ) >> 1 );at = as + 1;}else {as = s + ( ( t - s ) >> 1 ) - 1;at = as + 2;}}intmintv(void) {return ( t - s + 2 ) >> 1;}booloperator<(const Wed &oth) const {return as < oth.as || ( as == oth.as && at < oth.at );}};Wedw[MAXCPN];boolcan_hold_all(int n) {intcur_s, cur_t;intprv_t;inti;prv_t = (*w).mintv();for ( i = 1; i < n; i++ ) {cur_s = w[i].s;if ( cur_s < prv_t ) cur_s = prv_t;cur_t = cur_s + w[i].mintv();if ( cur_t > w[i].t ) return false;prv_t = cur_t;}return true;}intmain() {intn;inti;while ( scanf("%d", &n), n ) {for ( i = 0; i < n; i++ ) w[i].init();sort(w, w + n);if ( can_hold_all(n) ) puts("YES");else puts("NO");}return 0;}

单词解释:

integral:adj, 整数的

interrupt:vt, 中断,打断

ceremony:n, 典礼,以示

bless:vt, 祝福,保佑

legend:n, 传奇

priest:n, 牧师,神父

0 0
原创粉丝点击