UVa 1467 (贪心+暴力) Installations

题意:

一共有n项服务,每项服务有安装的时间s和截止时间d。对于每项任务,如果有一项超出截止时间,惩罚值为所超出时间的长度。问如何安装才能使惩罚值最大的两个任务的惩罚值之和最小。

分析:

如果是求总惩罚值的最小值,则按所有任务的截止时间排序,这样贪心的理由是,先完成截止时间早的任务至少不会是情况变得更坏。

虽然题目所求不是这个,但我们可以稍作修改。

设p为按上述贪心顺序安装任务,惩罚值最大的两个任务中靠后的那个位置。

枚举p之前的任务i,将第i个任务移到p后面执行,有可能减小两个最大惩罚值之和,所以维护一个最小值即可。

但还有一个问题就是,为什么不可能是移动两个任务到p后面得到最优解??

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4
 5 const int maxn = 500 + 10;
 6 int n, p;
 7 struct Job
 8 {
 9     int s, d;
10     Job(int s = 0, int d = 0):s(s), d(d) {}
11     bool operator < (const Job& a) const
12     {
13         return d < a.d;
14     }
15 }job[maxn];
16
17 int test(int x)
18 {
19     int t = 0, a = 0, b = 0, k = 0;
20     for(int i = 0; i <= p; ++i)
21     {
22         if(i == x) continue;
23         t += job[i].s;
24         k = max(0, t - job[i].d);
25         b = max(b, k);
26         if(b > a) swap(a, b);
27     }
28     t += job[x].s;
29     k = max(0, t - job[x].d);
30     b = max(b, k);
31     return a + b;
32 }
33
34 int main(void)
35 {
36     //freopen("1467in.txt", "r", stdin);
37     int T;
38     scanf("%d", &T);
39     while(T--)
40     {
41         scanf("%d", &n);
42         for(int i = 0; i < n; ++i)
43         {
44             int s, d;
45             scanf("%d%d", &s, &d);
46             job[i] = Job(s, d);
47         }
48
49         sort(job, job + n);
50         int t = 0, a = 0, b = 0;
51         for(int i = 0; i < n; ++i)
52         {
53             t += job[i].s;
54             if(t - job[i].d >= b)
55             {
56                 b = t - job[i].d;
57                 p = i;
58             }
59             if(b > a) swap(a, b);
60         }
61
62         int ans = a + b;
63         for(int i = 0; i < p; ++i)
64             ans = min(ans, test(i));
65
66         printf("%d\n", ans);
67     }
68
69     return 0;
70 }

代码君

时间: 2024-07-31 10:31:26

UVa 1467 (贪心+暴力) Installations的相关文章

uva 617- Nonstop Travel(暴力+数学)

题目链接:uva 617 - Nonstop Travel 题目大意:在一条路上有n个红绿灯,给出红绿灯的位置,以及绿灯,黄灯和红灯的时间,问现在以什么样的速度可以不同停止便通过这条路段.(速度只在30~60km/h) 解题思路:枚举速度,然后判断即可. 注意说黄灯也是可以过的,以及红绿灯的距离是以米为单位的. #include <cstdio> #include <cstring> const int N = 10; struct state { double dis; int

uva 1509 - Leet(暴力)

题目链接:uva 1509 - Leet 题目大意:给出k,表示一个字符可以对应k给字符编码,给出字符串1,问时候有符合的编码可以生成字符串2. 解题思路:暴力枚举,对于每个碰到的字符记录对应的编码. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 105; const int maxc = 200; int k, len1,

BZOJ 3671 NOI2014 随机数生成器 贪心+暴力

题目大意:.....有点长自己看吧 首先既然是排序后的序列字典序最小,那么一定要选尽量小的数字走 然后T是1~m*n的序列 所以不存在重复(一开始我居然把这个条件看漏了) 好的这题贪心 每次选择没有被标记的最小点,然后把左下方和右上方都标记掉(记得标记重复时break,不然就挂了) 注意5000*5000的数组开两个int就是极限了 开多了妥妥MLE 所以T数组记得重复利用 暴力跑了38秒 不过这题每一行能够选择的区域一定是连续的 可以对于每一行维护一个l和r 每次更新取最值即可 这个代码跑了2

01_传说中的车(Fabled Rooks UVa 11134 贪心问题)

问题来源:刘汝佳<算法竞赛入门经典--训练指南> P81: 问题描述:你的任务是在n*n(1<=n<=5000)的棋盘上放n辆车,使得任意两辆车不相互攻击,且第i辆车在一个给定的矩形R之内. 问题分析:1.题中最关键的一点是每辆车的x坐标和y坐标可以分开考虑(他们互不影响),不然会变得很复杂,则题目变成两次区间选点问题:使得每辆车在给定的范围内选一个点,任何两辆车不能选同一个点.  2.本题另外一个关键点是贪心法的选择,贪心方法:对所有点的区间,按右端点从小到大排序:每次在一个区间

【BZOJ】1028: [JSOI2007]麻将(贪心+暴力)

http://www.lydsy.com/JudgeOnline/problem.php?id=1028 表示不会贪心QAQ 按顺序枚举,如果能形成刻子那么就形成刻子,否则形成顺子.orz 证明?:因为按顺序枚举,所以当枚举到i,i一定要用完,所以因为>3个顺子和>3个刻子等价,所以考虑<3个顺子.如果i是刻子,假设我们用顺子,那么显然会剩下<=2个,因此不是最优的,所以有刻子就用刻子. 那么暴力枚举添加的,然后暴力枚举哪个是对子,最后暴力判断..n^3.. #include &l

Hdu 3697 Selecting courses(贪心+暴力)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3697 思路:将课程按照右端点从小到大排序,相同时按照左端点从小到大排序.选课开始时间只能是0,1,2,3,4,开始时间确定后每次选课时间确定,暴力枚举即可. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const in

UVa 11389 (贪心) The Bus Driver Problem

题意: 有司机,下午路线,晚上路线各n个.给每个司机恰好分配一个下午路线和晚上路线. 给出行驶每条路线的时间,如果司机开车时间超过d,则要付加班费d×r. 问如何分配路线才能使加班费最少. 分析: 感觉上是要先排序,然后时间最长的路线配另一个时间最短的路线. 这里就严格证明一下这样贪心的正确性. 以两条路线为例,其他情况都是类似的: 不妨假设:A1≥A2,B1≤B2,水平线代表d 情况一: 如图,司机一要付加班费,司机二不用,如果我们将B1.B2交换: 因为B1≤B2,所以付给司机一的加班费不会

CodeForces 398A Cards 贪心 暴力 瞎搞

搞了一晚上了快,各种YY乱搞啊,终于过了,一开始YY的都是错的,觉得 这道题目a,b的范围都是10^5,那就暴力枚举b被分成了几份,然后再继续YY,只用一个o去分隔x,这样最后剩下的o再集中在一起,也就是x的份数总是比o的份数多一份,也就是尽可能把x分开,尽可能把o集中在一块,前面都把x分开了,一个o分开两份x,后面还能有一大堆的o在一起,这样就满足了,然后又出错了,因为分成几份,有余数的,比如b = 6,你要分成4份,我以开始是分成 1  1  1  3这样子,这样不行,应该分成 1 1 2

uva 201 Squares 暴力

暴力 把边的信息装到一个field数组里面 第一维存水平线 第二维存竖直线 多重循环 先从边长为1正方形开始检查 每次检查都重新扫一下它的外圈 注意竖直线的地方它先给列坐标再给行坐标 输出有些繁琐 注意输出空行还有星星 #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <cmath