【题目链接】

ybt 1319:【例6.1】排队接水
洛谷 P1223 排队接水

【题目考点】

1. 贪心

2. 贪心选择性质的证明

要想证明贪心选择可以得到最优解,只需要证明最优解包含每一次的贪心选择。
使用数学归纳法:

  1. 证明最优解包含第一次的贪心选择
  2. 假设存在最优解包含前k次的贪心选择,证明该最优解包含第k+1次的贪心选择

【解题思路】

1. 证明贪心选择性质

贪心选择:每次选择接水时间最短的人去接水
贪心选择性质的证明:
设n个人的编号为1,2,3,…,n

  1. 证明:存在最优解,第一个接水的人是通过贪心选择得到的。
    接水时长最短的人编号为ggg,其接水时间为TgT_gTg​

使用反证法:假设对于所有最优解,第一个接水的人都不可以是贪心选择得到的人g。
则对于某种最优解,其接水顺序为d1,d2,...,dnd_1,d_2,...,d_nd1​,d2​,...,dn​,假设g是第m个接水的人,即dm=g(m>1)d_m = g (m > 1)dm​=g(m>1),记第1个接水的人的编号为a,即d1=ad_1 = ad1​=a
由于g的所有人中打水时间最短的人,那么一定有Ta>TgT_{a} > T_{g}Ta​>Tg​
如果交换aaa与ggg,考虑总接水时间的变化:

  • 从d2∼dm−1d_2\sim d_{m-1}d2​∼dm−1​一共m−2m-2m−2个人,每人等待的时间减少了TaT_aTa​增加了TgT_gTg​,总减少时间为(m−2)(Ta−Tg)(m-2)(T_a-T_g)(m−2)(Ta​−Tg​)
  • g等待的时间从Ta+∑i=2m−1TdiT_a+\sum_{i=2}^{m-1}T_{di}Ta​+∑i=2m−1​Tdi​变为000,等待时间减少Ta+∑i=2m−1TdiT_a+\sum_{i=2}^{m-1}T_{di}Ta​+∑i=2m−1​Tdi​
  • a的等待时间从000变为Tg+∑i=2m−1TdiT_g+\sum_{i=2}^{m-1}T_{di}Tg​+∑i=2m−1​Tdi​,等待时间减少−(Tg+∑i=2m−1Tdi)-(T_g+\sum_{i=2}^{m-1}T_{di})−(Tg​+∑i=2m−1​Tdi​)
  • 总减少的等待时间为上面三者的加和,结果为(m−1)(Ta−Tg)(m-1)(T_a-T_g)(m−1)(Ta​−Tg​)。由于m>1m>1m>1且Ta>TbT_a>T_bTa​>Tb​,那么(m−1)(Ta−Tg)>0(m-1)(T_a-T_g) > 0(m−1)(Ta​−Tg​)>0

因此,如果交换a与g,总接水时间会减少。这与当前解是可以使平均接水时间最小的最优解相矛盾,因而原命题得证。

  1. 证明:存在最优解,假设前k个人接水的人都是通过贪心选择得到的,第k+1个接水的人也通过贪心选择得到,即选择剩下的接水时长最短的人。

证明方法与上面第1点的证明方法类似,把证明中的“第一个接水的人”改为“第k+1个接水的人”即可,不再赘述。

以上证明了该问题具有贪心选择性质,即每次选择接水时间最短的人去接水,可以使n个人的平均等待时间最小。

2. 具体做法

结构体中保存人的编号和打水时间,按打水时间升序对结构体对象进行排序。计算所有人的等待时间加和,最后除以总人数。

3. 排序方法

该题说当时间重复时,按照输入顺序输出。虽然它说“用sort是可以的”,但严格来讲,这里按照输入顺序将其加入数组中,而后按照打水时间进行排序。如要让相同打水时间的元素保持输入时的先后顺序,则理论上必须选用稳定的排序算法。所以这里我们使用stable_sort进行排序。

【题解代码】

解法1:贪心,使用stable_sort进行排序

#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct Time
{double t;int i;//t:时间 i:人的编号
};
Time a[N];
bool cmp(const Time &a, const Time &b)
{return a.t < b.t;
}
int main()
{int n;double sumTime = 0, waitTime = 0;cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i].t;a[i].i = i;}stable_sort(a+1, a+1+n, cmp);for(int i = 1; i <= n; ++i){sumTime += waitTime;//waitTime:当前这个人已经等的时间 waitTime += a[i].t;cout << a[i].i << ' ';}cout << endl << fixed << setprecision(2) << sumTime / n; return 0;
}

解法2:贪心 手写归并排序

#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct Time
{double t;int i;//t:时间 i:第几个
};
Time a[N], t[N];
void mergeSort(int l, int r)//归并排序
{if(l >= r)return;int mid = (l+r)/2;mergeSort(l, mid);mergeSort(mid+1, r);int i = l, j = mid+1, ti = l;while(i <= mid && j <= r){if(a[i].t < a[j].t)t[ti++] = a[i++];elset[ti++] = a[j++];}while(i <= mid)t[ti++] = a[i++];while(j <= r)t[ti++] = a[j++];for(int k = l; k <= r; ++k)a[k] = t[k];
}
int main()
{int n;double sumTime = 0, waitTime = 0;cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i].t;a[i].i = i;}mergeSort(1, n);for(int i = 1; i <= n; ++i){sumTime += waitTime;//waitTime:当前这个人已经等的时间 waitTime += a[i].t;cout << a[i].i << ' ';}cout << endl << fixed << setprecision(2) << sumTime / n; return 0;
}

信息学奥赛一本通 1319:【例6.1】排队接水 | 洛谷 P1223 排队接水相关推荐

  1. 洛谷——P1223 排队接水

    题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行,第一行为n:第二行分别 ...

  2. 【例1】 0/1背包《信息学奥赛一本通》【解法一】 02

    /* [例1] 0/1背包<信息学奥赛一本通>[解法一] 02 http://ybt.ssoier.cn:8088/problem_show.php?pid=1267 */ #includ ...

  3. 【例8】合唱队形(《信息学奥赛一本通第五版》)

    /* [例8]合唱队形(<信息学奥赛一本通第五版>) http://ybt.ssoier.cn:8088/problem_show.php?pid=1264 [问题描述] N位同学站成一排 ...

  4. 信息学奥赛一本通 2021:【例4.6】最大公约数

    [题目链接] ybt 2021:[例4.6]最大公约数 [题目考点] 1. while循环 2. 求最大公约数 辗转相减法 辗转相除法 [解题思路] 解法1:枚举 取较小数字,从该数字的值开始从大到小 ...

  5. 信息学奥赛一本通(2032:【例4.18】分解质因数)

    2032:[例4.18]分解质因数 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 582     通过数: 376 [题目描述] 把一个合数分解成若干个质因数乘积 ...

  6. 信息学奥赛一本通——2062:【例1.3】电影票

    2062:[例1.3]电影票 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 57341     通过数: 34230 [题目描述] 已知一位小朋友的电影票价是10 ...

  7. 信息学奥赛一本通 1278:【例9.22】复制书稿(book) | 洛谷 P1281 书的复制

    [题目链接] ybt 1278:[例9.22]复制书稿(book) 洛谷 P1281 书的复制 [题目考点] 1. 动态规划:线性动规 [解题思路] 该题可以抽象为:将由m个数字构成的序列分成k个子段 ...

  8. 信息学奥赛一本通1267:【例9.11】01背包问题(二维dp与滚动数组优化)

    [题目描述] 一个旅行者有一个最多能装 MM 公斤的背包,现在有 nn 件物品,它们的重量分别是W1,W2,...,WnW1,W2,...,Wn,它们的价值分别为C1,C2,...,CnC1,C2,. ...

  9. 信息学奥赛一本通C++语言-----2036:【例5.3】开关门

    [题目描述] 宾馆里有n(2≤n≤1000)n(2≤n≤1000) 个房间,从1∼n1∼n 编了号.第一个服务员把所有的房间门都打开了,第二个服务员把所有编号是22 的倍数的房间"相反处理& ...

最新文章

  1. 编辑神器VIM下安装zencoding
  2. 2021 年中国敏捷行业现状调查全面启动
  3. linux 卡在grub_详解ubuntu双系统启动时卡死解决办法
  4. Sql Server 查看所有存储过程或视图的位置及内容
  5. DCMTK:OFStandard类的测试程序
  6. HDU 4325 离散化+树状数组 或者 不使用树状数组
  7. 几种常用的排序算法之JavaScript实现
  8. es数据频繁的更新_es之文档更新过程中并发冲突问题
  9. 【Computer Organization】The Core Design Thinking of single cycle CPU
  10. 云栖专辑 | 阿里开发者们的第11个感悟:拥抱变化,用正确的方法对待工作
  11. 非纯 []!()输出 始皇帝 推导过程
  12. Android使用相机demo
  13. 说明使用tc编程的一般步骤 c语言,TC编程手册详解-完整版.doc
  14. 将20180608141920转成date格式
  15. Ubuntu+CUDA+OpenCV+Caffee安装
  16. KOOCAN的影视资讯——那些惊艳到你的女鬼
  17. 2021年实现团队成功的4步绩效管理周期
  18. linux之OPERATION(运维)一
  19. 安卓打包:jks Invalid keystore format 报错解决
  20. DFS分布式文件存储系统

热门文章

  1. 使用Microsoft EnterpriseLibrary(微软企业库)日志组件把系统日志写入数据库和xml文件...
  2. WPF设置全局快捷键
  3. 多个集合合并成没有交集的集合-实现
  4. uitableview 弹性_iOS UITableView滚动头图 拉伸放大效果 (头部弹性效果) 增加iOS11支持 附有demo...
  5. angular input_快速地上手Angular组件开发
  6. 巨坑!这公司的行为,挺适合清明节!
  7. 凉了!张三同学没答好「进程间通信」,被面试官挂了....
  8. MiniDao1.7.1 版本发布,轻量级Java持久化框架
  9. Windows下Yarn安装与使用
  10. IntelliJ IDEA下的使用git