设为首页 收藏本站
查看: 992|回复: 0

[经验分享] HDU Task Schedule && ZOJ Talented Chef

[复制链接]

尚未签到

发表于 2015-11-26 07:02:10 | 显示全部楼层 |阅读模式
                                                                   
Task Schedule

  
  题目链接:Click Here~
  题目解析:
     给你N任务,M台机器。每个任务都有开始的时间和结束的时间以及要完成这项任务所要花费的时间。问你是否可以在规定的时间内完成所有的任务。
  


  算法分析:
     我的做法是网络流,求出最大流。而在网上看到别人似乎可以用贪心过的。然后,一试果然是可以的。我发现这种题还有一种类型就是给你N个任务M台机器要你在最短的时间内求出。下面还会给出这种类型的,这样就可以很好的进行对比学习了。
  


  建模分析:
      我们可以想一想有N个任务,M台机器。是不是就说明每天至多可以完成M项任务?而且每个任务都有自己的开始时间和结束时间。换句话说,每个任务每天只要在规定的时间内都可以被完成一次。所以,我们从中想到了建图的思路。即,建立两个源点和汇点。把每个任务跟源点相连,流量为所需要的天数。而任务跟规定的时间相连,流量为1,因为一个任务每天只能被完成一次。而每天跟汇点相连,流量为M。因为,每天至多可以完成M项任务。
  


  #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = ~0U >> 2;
const int MAXN = 1e3 + 10;
struct Edge{
int from,to,cap,flow;
Edge(int f,int t,int c,int _f)
:from(f),to(t),cap(c),flow(_f){};
};
class MaxFlow{
public:
void Init();
void AddEdge(int form,int to,int cap);
bool BFS();
int DFS(int u,int a);
int Maxflow();
bool Solve(int n,int m);
private:
vector<Edge> edges;
vector<int> G[MAXN];
int S,T,N,M;
int cur[MAXN],d[MAXN];
bool vst[MAXN];
};
void MaxFlow::Init()
{
for(int i = 0;i < MAXN;++i)
G.clear();
edges.clear();
}
inline void MaxFlow::AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
int sz = edges.size();
G[from].push_back(sz-2);
G[to].push_back(sz-1);
}
bool MaxFlow::BFS()
{
memset(vst,false,sizeof(vst));
vst[S] = true; d[S] = 0;
queue<int> Q;
Q.push(S);
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i = 0;i < (int)G.size();++i){
Edge& e = edges[G];
if(!vst[e.to]&&e.cap > e.flow){
d[e.to] = d + 1;
vst[e.to] = true;
Q.push(e.to);
}
}
}
return vst[T];
}
int MaxFlow::DFS(int u,int a)
{
if(u==T||a==0)
return a;
int f,flow = 0;
for(int& i = cur;i < (int)G.size();++i){
Edge& e = edges[G];
if(d[e.to]==d+1&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow += f;
edges[G^1].flow -= f;
flow += f;
a -= f;
if(a==0)break;
}
}
return flow;
}
int MaxFlow::Maxflow()
{
int flow = 0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow += DFS(S,INF);
}
return flow;
}
bool MaxFlow::Solve(int n,int m)
{
Init();
int p,s,e,sum = 0,MAXD = 0;
S = 0; N = n; M = m;
for(int i = 1;i <= N;++i){
scanf(&quot;%d%d%d&quot;,&p,&s,&e);
sum += p;
MAXD = max(MAXD,e);
AddEdge(S,i,p);
for(int j = s;j <= e;++j)
AddEdge(i,j+N,1);
}
T = N+M+1;
for(int i = 1+N;i <= MAXD+N;++i)
AddEdge(i,T,M);
int maxflow = Maxflow();
return sum == maxflow;
}
MaxFlow mf;
int main()
{
//    freopen(&quot;Input.txt&quot;,&quot;r&quot;,stdin);
int T,n,m;
scanf(&quot;%d&quot;,&T);
for(int kase = 1;kase <= T;kase++){
scanf(&quot;%d%d&quot;,&n,&m);
if(mf.Solve(n,m))
printf(&quot;Case %d: Yes\n&quot;,kase);
else
printf(&quot;Case %d: No\n&quot;,kase);
puts(&quot;&quot;);
}
return 0;
}



  贪心的思路:
      我们可以根据贪心的思想,每一天都去开始时间最近的,即,最早开始的。如果,最早开始的多于M个怎么办?
  其实这时候要再一次运用贪心思想,先完成要完成该项任务剩余时间少的。最后根据进行模拟,而模拟过程我们又可以运用优先队列来很好的帮助我们完成。
  


  #include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 500+10;
struct Node{
int s,e,p,x;
bool operator<(const Node &rhx)const{
return s != rhx.s ? s > rhx.s:x > rhx.x;
}
};
int main()
{
//    freopen(&quot;Input.txt&quot;,&quot;r&quot;,stdin);
int T,N,M;
scanf(&quot;%d&quot;,&T);
for(int kase = 1;kase <= T;kase++)
{
bool flag = true;
int i,j,s,e,p,MAXD = 0;
Node tmp;
priority_queue<Node> Q;
scanf(&quot;%d%d&quot;,&N,&M);
for(i = 1;i <= N;++i){
scanf(&quot;%d%d%d&quot;,&p,&s,&e);
e++;
MAXD = max(MAXD,e);
if(s+p<=e){
tmp.s = s;
tmp.e = e;
tmp.p = p;
tmp.x = e-(s+p);
Q.push(tmp);
}
else
flag = false;
}
printf(&quot;Case %d: &quot;,kase);
if(!flag){
puts(&quot;No&quot;);
puts(&quot;&quot;);
continue;
}
//模拟每天M台机器工作的过程
for(i = 1;i < MAXD;++i){
bool sub = true,out = false;
for(j = 1;j <= M;++j){
if(Q.empty()){        //所有工作已经完成
out = true;
break;
}
tmp = Q.top();
if(tmp.s > i){
sub = false;
break;
}
Q.pop();
tmp.p--;
tmp.s = i+1;
tmp.x = tmp.e-(tmp.s+tmp.p);
if(tmp.x < 0){
out = true;
flag = false;
break;
}
if(tmp.p==0)
N--;
else
Q.push(tmp);
}
//更新优先队列中工作起始时间
for(;j<=N&&!out&⊂++j){
tmp = Q.top();
if(tmp.s > i)
break;
Q.pop();
tmp.s = i+1;     // 更新起始时间
tmp.x = tmp.e-(tmp.s+tmp.p);
if(tmp.x < 0){
out = true;
flag = false;
break;
}
Q.push(tmp);
}
if(out)
break;
}
if(flag)
puts(&quot;Yes&quot;);
else
puts(&quot;No&quot;);
puts(&quot;&quot;);
}
return 0;
}



  


  题目链接:Click Here~
  题目分析:
     这是一道浙江省的省赛题。就是给你N个要烹饪的东西,M口锅。每口锅每次只能烹饪一种东西,问你最短的时间烹饪完所有的东西要多久。
  


  算法分析:
     我也不知道这题确切考查的是啥。我只知道我这跟腾讯马拉松的一道题一样的。所以当时比赛的时候我就水了。
  我一开始是用优先队列模拟的,结果超时了。后来直接换成了公式,直接算,就Y了。具体思路是这样的,我们可以想到每种菜都要x天。而总共要进行的次数我们假设为SUM,则平均我们要烹饪SUM/M次。但是有两种情况是特殊的,就是其中有某道菜的天数X > SUM/M,这时候就有可能到最后的时候,就剩下这一道菜了,而锅剩下了,所以平均&#20540;这时候显然是不对的,所以,我们结果要取X。还有就是N <= M,就是无论在什么情况下没一次每一道菜都保证可以被烹饪到,所以,此时我们只要去最大的次数就好了。其他的就是平均&#20540;了。
  #include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
//    freopen(&quot;In.txt&quot;,&quot;r&quot;,stdin);
int T,n,m,v;
scanf(&quot;%d&quot;,&T);
while(T--)
{
int tim = 0,big = 0;
scanf(&quot;%d%d&quot;,&n,&m);
for(int i = 0;i < n;++i){
scanf(&quot;%d&quot;,&v);
tim += v;
big = max(big,v);   //zhao dao zui da shi jian
}
if(n <= m){
printf(&quot;%d\n&quot;,big);
continue;
}
int ans = tim / m;
if(tim%m)
ans++;
if(ans < big)  //qizhong de dan ge hai geng da
printf(&quot;%d\n&quot;,big);
else
printf(&quot;%d\n&quot;,ans);
}
return 0;
}



  


  


  


  


  


    
  


  


  


  


  &#65279;&#65279;

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-143573-1-1.html 上篇帖子: codechef-Chef and Prime Divisors 下篇帖子: codechef Chef and sequence
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表