题意

早期的多程序操作系统常把所有的可用内存划分为一些大小固定的区域,不同的区域一般大小不同,而所有区域的大小之和为可用内存的大小。给定一些程序,操作系统需要给每个程序分配一个区域,使得他们可以同时执行。可是每个程序的运行时间可能和它所占有的内存区域大小有关,因此调度并不容易。

编程计算最优的内存分配策略,既给定m个区域的大小和n个程序在各种内存环境下的运行时间,找出一个调度方案,使得平均结束时刻尽量小。具体来说,你需要给每个程序分配一个区域,使得没有两个程序同时在同一个时间运行在同一个内存区域中,而所有程序分配的区域大小都不小于该程序的最低内存需求。程序对内存的需求不会超过最大内存块的大小。

分析

这个题最重要的是明白一个很重要的结论:在同一个内存中,第倒数第k个执行的程序对于该内存总结束时间的贡献为kT,T为该程序在该内存下的运行时间。

有了这个结论,建图就并不难了。

下面我们来构造二分图,X结点为n个程序,Y结点为n*m个位置,其中位置(j,p)表示第j个内存的倒数第p个执行的程序。每个结点X和Y结点(j,p)之间连一条边权为pTi,j的边,然后求最小权匹配就可以。

并不是每个匹配都对应一个合法方案,但是,最佳匹配一定是对应一个合法方案。

我下面用费用流写的代码并不能AC,等以后看看是不是能找到bug。

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue> using namespace std;
const int maxn=+;
const int maxm=+;
const int INF=1e9;
struct MCMF{
int head[maxn],to[maxm],Next[maxm],from[maxm],flow[maxm],cap[maxm];
long long cost[maxm];
int n,m,s,t,sz;
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn]; void init(int n){
this->n=n;
sz=-;
memset(head,-,sizeof(head));
}
void AddEdge(int a,int b,int ca,long long co){
++sz;
to[sz]=b,from[sz]=a,Next[sz]=head[a],head[a]=sz;
flow[sz]=,cap[sz]=ca,cost[sz]=co;
++sz;
to[sz]=a,from[sz]=b,Next[sz]=head[b],head[b]=sz;
flow[sz]=ca,cap[sz]=ca,cost[sz]=-co;
}
bool BellmanFord(int s,int t,int &Flow,long long &Cost){
for(int i=;i<=n;i++)d[i]=INF;
memset(inq,,sizeof(inq));
d[s]=;inq[s]=;p[s]=-;a[s]=INF;
queue<int>Q;
Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
inq[u]=;
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(cap[i]>flow[i]&&d[v]>d[u]+cost[i]){
d[v]=d[u]+cost[i];
p[v]=i;
a[v]=min(a[u],cap[i]-flow[i]);
if(!inq[v]){
Q.push(v);
inq[v]=;
}
}
}
}
if(d[t]==INF)return false;
Flow+=a[t];
Cost+=(long long)d[t]*(long long)a[t];
int u=t; while(u!=s){
flow[p[u]]+=a[t];
flow[p[u]^]-=a[t];
u=from[p[u]];
}
return true;
} long long Mincost(int s,int t){
int Flow=;
long long Cost=;
while(BellmanFord(s,t,Flow,Cost));
return Cost;
}
}mcmf;
const int maxN=;
const int maxM=;
int n,m,kase;
int Size[maxM];
int p[maxN][maxN],tim[maxN][maxN],Time[maxN];
int main(){
kase=;
while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
if(kase){
printf("\n");
} ++kase;
for(int i=;i<=m;i++)
scanf("%d",&Size[i]);
for(int i=;i<=n;i++){
scanf("%d",&p[i][]);
for(int j=;j<=p[i][];j++){
scanf("%d%d",&p[i][j],&tim[i][j]);
}
}
mcmf.init(n+n*m+);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(p[i][]>Size[j])continue;
int T=INF;
for(int l=;l<=p[i][];l++){
if(p[i][l]<=Size[j]){
T=min(T,tim[i][l]);
}
}
for(int l=;l<=n;l++){
mcmf.AddEdge(i,j*n+l,,l*T);
}
}
}
for(int i=;i<=n;i++)
mcmf.AddEdge(,i,,);
for(int i=n+;i<=n*m+n;i++)
mcmf.AddEdge(i,n*m+n+,,);
long long res=mcmf.Mincost(,n*m+n+);
double ans=(double)res/n;
printf("Case %d\n",kase);
printf("Average turnaround time = %.2f\n",ans); int ANS[maxN][maxN],bel[maxN];
memset(ANS,-,sizeof(ANS));
memset(Time,,sizeof(Time));
for(int i=;i<=n;i++){
for(int j=mcmf.head[i];j!=-;j=mcmf.Next[j]){
if(j%)continue;
if(mcmf.cap[j]>mcmf.flow[j])continue;
int v=mcmf.to[j];
int a=v/n,b=v%n;
if(b==){
b=n;
a--;
}
ANS[a][b]=i;
bel[i]=a;
Time[i]=mcmf.cost[j]/b;
}
}
int F[maxN],T[maxN];
for(int i=;i<=m;i++){
int st=;
for(int j=n;j>=;j--){
if(ANS[i][j]!=-){
st=j;
break;
}
}
int all=;
for(int j=st;j>=;j--){
int x=ANS[i][j];
F[x]=all,T[x]=all+Time[x];
all=T[x];
}
} for(int i=;i<=n;i++){
printf("Program %d runs in region %d from %d to %d\n",i,bel[i],F[i],T[i]);
}
}
return ;
}

最新文章

  1. 单页Web应用优缺点
  2. MySQL按照汉字的拼音排序
  3. Android 5.0属性
  4. Android成长日记-仿跑马灯的TextView
  5. Binary Tree Level Order Traversal II
  6. 实现Ecshop商品跳到淘宝、京东等的购买链接
  7. window删除损坏无法打开的文件
  8. IAP沙盒测试帐号无法购买的问题
  9. 什么是系统平均负载(Load average)
  10. 【iOS】控件截图、MP4格式视频流和m3u8格式视频流截取某一帧功能的实现
  11. python 中的re模块,正则表达式
  12. nginx常用指令
  13. DataTable不能通过已删除的行访问该行的信息解决方法
  14. Git实战手册(二): 标签应用和版本管理
  15. 启动eclipse弹出提示Version 1.7.0_79 of the JVM is not suitable for this product. Version: 1.8 or greater is required怎样解决
  16. Git中的文件状态和使用问题解决
  17. Postman接口自动化--Postman Script脚本功能使用详解
  18. svn 节点处冲突 解决
  19. easyui combotree模糊查询
  20. SEL和IMP

热门文章

  1. decorator and @property
  2. hadoop 之Hadoop生态系统
  3. Wordpress网站添加七牛云cdn
  4. java nio和bio
  5. (转)Android短信的发送和接收监听
  6. MySql触发器实现数据同步学习
  7. 301重定向方法大全及SEO中网址规范化,看着不错先收下
  8. js点击按钮触发事件的方法
  9. 竖屏拍照,但是sd卡中却是横屏解决方法
  10. 第三方登录之微信登录,基于ThinkSDK