题意

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

编程计算最优的内存分配策略,既给定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 ;
}

【LA2238 训练指南】固定分区内存管理 【二分图最佳完美匹配,费用流】的更多相关文章

  1. UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)

    UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

  2. UVa 11383 少林决胜(二分图最佳完美匹配)

    https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数 ...

  3. Ants(二分图最佳完美匹配)

    Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6904   Accepted: 2164   Special Ju ...

  4. UVA - 1045 The Great Wall Game(二分图最佳完美匹配)

    题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...

  5. 【LA4043 训练指南】蚂蚁 【二分图最佳完美匹配,费用流】

    题意 给出n个白点和n个黑点的坐标,要求用n条不相交的线段把他们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接一条线段. 分析 结点分黑白,很容易想到二分图.其中每个白点对应一个X结 ...

  6. ZOJ-3933 Team Formation (二分图最佳完美匹配)

    题目大意:n个人,分为两个阵营.现在要组成由若干支队伍,每支队伍由两个人组成并且这两个人必须来自不同的阵营.同时,每个人都有m个厌恶的对象,并且厌恶是相互的.相互厌恶的人不能组成一支队伍.问最多能组成 ...

  7. UVa 1349 - Optimal Bus Route Design(二分图最佳完美匹配)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. UVALive 2238 Fixed Partition Memory Management 固定分区内存管理(KM算法,变形)

    题意:目前有一部分可用内存,分为m个大小固定的区域.现有n个程序要执行,每个程序在不同大小的内存中运行所需的时间不同,要使运行完所有程序所耗时最少,问每个程序在哪块区域中从什么时间运行到什么时间,以及 ...

  9. UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配,KM算法)

    题意: 有n个蚂蚁n棵树,蚂蚁与树要配对,在配对成功的一对之间连一条线段,要求所有线段不能相交.按顺序输出蚂蚁所匹配的树. 思路: 这个题目真是技巧啊,不能用贪心来为每个蚂蚁选择最近的树,这样很可能是 ...

随机推荐

  1. piwik docker 安装

    备注: 生产环境使用docker-compose  1. 安装docker && docker-compose    此处略过 2. 下载docker-compose  的文件   h ...

  2. Linux make menuconfig报错 Your display is too small to run Menuconfig!

    在没有全屏的状态下执行 make menuconfig,如果报下面的错误,表示终端的窗口太小,需要放大窗口或者全屏操作. ## using defaults found in /dev/null#Yo ...

  3. elasticsearch 6.0.0及之后移除了一个索引允许映射多个类型的操作(Removal of mapping types)

    分给线一下内容为理解错误内容,实际允许建立父子分档,只是类型改成来 join 官方demo: join datatypeedit The join datatype is a special fiel ...

  4. yii2自定义500错误

    由于项目想加预警监控,有一块儿是涉及到程序内部错误的500,这样的错误级别比较高,所以就需要捕获这样的错误,顺便自定义了一把视图样式 看了这篇博客,知道了如何去自定义自己错误页面 : http://t ...

  5. 利用反射及ActionFilterAttribute实现MVC权限管理

    1.利用反射获取当前程序集下的所有控制器和方法,拼接后写入到数据库. public void GetRightInfo() { ; var controllerTypes = Assembly.Get ...

  6. 螺旋填数:读入两个整数m,n,输出一个m行n列的矩阵,这个矩阵是1~m*n这些自然数按照右、下、左、上螺旋填入的结果。

    package Day8_06; /*读入两个整数m,n,输出一个m行n列的矩阵,这个矩阵是1~m*n这些自然数按照右.下.左.上螺旋填入的结果. * 例如读入数字4,5,则输出结果为: * 1 2 ...

  7. offset()和position()

    网上百度都有的说明是 offset():获取匹配元素在当前视口的相对偏移. position():获取匹配元素相对父元素的偏移. 如果单纯写这两句话,这个博客毫无意义 这里我写下他俩的使用情况,希望对 ...

  8. Java-Runoob:Java Stream、File、IO

    ylbtech-Java-Runoob:Java Stream.File.IO 1.返回顶部 1. Java 流(Stream).文件(File)和IO Java.io 包几乎包含了所有操作输入.输出 ...

  9. 使用Java读取配置文件

    实现起来,相对比较简单,留个备案吧,废话也不多说,请看代码: package com.jd.***.config; import org.junit.*; import java.io.IOExcep ...

  10. python复习之路-Day01

    数据类型初识 1.数字 2 是一个整数的例子.长整数 不过是大一些的整数.3.23和52.3E-4是浮点数的例子.E标记表示10的幂.在这里,52.3E-4表示52.3 * 10-4.(-5+4j)和 ...