L. Working Plan (优先队列 贪心思维 课表安排) ICPC Seoul 2018

2023-10-31 19:38

本文主要是介绍L. Working Plan (优先队列 贪心思维 课表安排) ICPC Seoul 2018,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述传送门
思路:

  • 现有m个人和n天的课表,要求安排一个可行方案,满足第j天有d[j]个人工作,第i个人总共工作w[i]天。且每个人一开始工作就必须连续工作w天,然后至少休息h天才能工作。如果有可行解第一行输出"1",然后输出m行,每i行含w[i]/w个数,表示第i个人每次工作的开头那天;无解直接输出"-1"。
  • 从头按顺序开始安排每一天工作的任选,首选工作量最大的且可以工作(既没有在进行上一次工作,也休息了至少h天;且后w天都需要人工作)的人。
  • 这个时候就用一个优先队列来存m个人的当前工作量情况,且用一个队列过渡。
  • 详细见代码。

代码实现:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ll long long
#define int long long
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
using namespace std;
const int  inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll   mod = 1e9 + 7;
const int  N = 2005;int m, n, w, h, ww, d[N];
vector<int> a[N];struct cmp{  //优先队列重载bool operator()(const pii p1, const pii p2){return p1.first < p2.first;}
};priority_queue <pii, vector<pii>, cmp> qw;bool check(int bg, int id){//如果这个人当前还不能工作if(a[id].size() && a[id].back()+w+h-1>=bg) return 0;//如果当前天已经不再需要人工作for(int i = bg; i < bg+w; i ++)if(d[i] <= 0) return 0;return 1;
}signed main()
{IOS;cin >> m >> n >> w >> h;bool ok = 1;for(int i = 1; i <= m; i ++){cin >> ww; qw.push({ww, i});if(ww%w) ok = 0;}for(int i = 1; i <= n; i ++) cin >> d[i];
//    while(qw.size()){cout << qw.top().first << endl; qw.pop();}if(!ok) cout << -1 << endl;  //如果某个人的初始工作量不能整除w,就不可能实现正好w[i]的工作量else{ok = 1;for(int i = 1; i <= n; i ++){if(!d[i]) continue;queue<pii> q;while(qw.size()&&d[i]){int id = qw.top().second, da = qw.top().first; qw.pop();if(check(i, id)){ //如果此人当前可以工作,且后w天也需要人工作
//                    cout << "i:" << i << " " << "di:" << d[i] << endl;a[id].push_back(i);q.push({da-w, id}); //更新此人的工作量for(int j = i; j < i+w; j ++) d[j] --; //后w天需要工作的人数都-1}else q.push({da, id}); //如果不能工作就直接进行下一轮筛选}
//            cout << "i:" << i << " " << "di:" << d[i] << endl;if(d[i]){ok = 0; break;}  //如果所有人都安排完了却依旧不能满足当天所需的工作人数while(q.size()){ //将临时队列q里的数据转入优先队列qw中qw.push(q.front());q.pop();}}while(qw.size()){if(qw.top().first){ok = 0;  //如果最好还有某一天所需工作人数不够
//                cout << "id:" << qw.top().second << " " << "id:" << qw.top().first << endl;}qw.pop();}if(!ok) cout << -1 << endl;else{cout << 1 << endl;for(int i = 1; i<= m; i ++)for(int j = 0; j < a[i].size(); j ++)cout << a[i][j] << " \n"[j == a[i].size()-1];}}return 0;
}

这篇关于L. Working Plan (优先队列 贪心思维 课表安排) ICPC Seoul 2018的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/317645

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

ural 1820. Ural Steaks 贪心

1820. Ural Steaks Time limit: 0.5 second Memory limit: 64 MB After the personal contest, happy but hungry programmers dropped into the restaurant “Ural Steaks” and ordered  n specialty steaks

ural 1014. Product of Digits贪心

1014. Product of Digits Time limit: 1.0 second Memory limit: 64 MB Your task is to find the minimal positive integer number  Q so that the product of digits of  Q is exactly equal to  N. Inpu