题意:计算机中有一些固定大小的内存,内存越大,处理速度越快。对于一个程序,加入不同的内存空间,处理所需时间不同。现给出m个内存空间,n个程序,对于每个程序程序,有k组数据(s,t),分别表示当程序 i 在某个内存环境s下对应的运行时间t。当有一个内存空间为si,一个程序的2组数据a,b,满足as<=si<bs,那么这个程序放到该内存中的运行时间是at(取下界)。已知不同的内存空间可以同时运行,同一个内存空间的程序在某一时刻只能有一个在运行。又知道一个程序从提交给计算机到运行结束这段时间为“运行时间”(所有程序在0时刻同时提交)。求出最小平均“运行时间”=总“运行时间”/n个程序,并给出每个程序在哪个内存区内运行(内存区编号1~m),以及该程序在内存区内是从何时开始运行,何时结束的。(保证不会出现程序的最小需求内存>最大内存空间)

分析:

  很复杂的题意,直观感觉就是所求的量很多,而且并非直接求最小值,是要具体的把方案求解出来。想到这里应该能确定用图论解决。进一步的,要用什么来处理,排除法也能想到匹配(其实我在刷图论专题= =)。

  确定了算法,就明确了方向,一侧必然是n个程序。那么另一侧应该是什么呢?我们求的是平均“运行时间”,那么可行顶标Lx、Ly之和就应该是最小的总“运行时间”。我们先考虑总运行时间应该怎么算呢?假设一个内存空间 i 按顺序运行3个程序a、b、c,那么这个程序总的运行时间Ti=at+(at+bt)+(at+bt+ct)=3*at+2*bt+1*ct

  (至此应该都能想到,接下来根据这个式子建模)。

  我们发现,a程序虽然是第一个完成,但它受这个内存中程序的数量以及运行次序的影响,实际贡献了3*at的时间。当我们拿到一个程序a,并放入某个内存 i 中。首先根据程序的 k 组数据可以确定at的大小。如果假定这个内存中有x个程序,a程序排在第y个,于是构造一个点(i,x,y),那么我们就可以确定边权为(x-y+1)*at。

  如此构造有何不妥之处呢?

  做最佳二分完美匹配,每个程序都对应于一个点(i,x,y),得到最小值。会不会不合常理呢?会的...因为是在交错树上沿等边增广,这里每次调整后,都必然出现许多等边((x-y+1)的大小同时受x和y影响),虽然调整交错树可能会出现多条等边,但那是巧合(数据相等),而非必然。这种必然导致的就是出现了大量的符合最小值的方案,一个任务,可以匹配点(i,x,y),也可以匹配点(i,(x+1),(y+1)),反正都在内存 i 内,at为定值。而这种任意分配是不合理的,因为最后无法确定顺序:一个内存中,若有x个程序,它的(i,x,1)可能都已经匹配,但是本该与(i,x,2)(i,x,3)匹配的点却与(i,(x-1),1)(i,(x-1),2)匹配。

  建模失败了,那么有什么可取之处?该如何改进呢?

  先找问题:1、点的构造决定了边权(x-y+1)*at,x、y同时影响是等边过多;2、时间复杂度高:一侧有S=n个点,一侧有T=m*n*n=mn2个点,所以总复杂度S*T*(S+T)=m2n5=10的10次方 = =

  重新建点,将x,y两个变量简化为一个变量,观察式子Ti=3*at+2*bt+ct,从后往前逐次+1;又边权(x-y+1)*at 中,(x-y+1)本身就表示的是系数,也可以理解为倒数第几个。于是,新的构点取(i,p):在第 i 个内存中以倒数第p个的身份出现,边权就是p*at。

  同样做最佳完美匹配。已知一种完美匹配是任意的,不仅不一定是最佳,而且不一定不合理。但是最佳二分完美匹配,一定是合理的。因为(i,p)与权值p*at相互唯一对应,杜绝了之前多条等边的情况。又有,若在内存 i 中有3个程序a,b,c,分别对应( i,1)( i,2)( i,4),必然不是最佳,c对应于( i,3)有“更佳”的权值3*ct。再考虑复杂度,S=n,T=m*n,总复杂度S*T*(S+T)=m2n3=10的7次方,可以接受。

注意:

1、S,T两侧的数组因为点数的不同,要分开处理。

2、关于n个程序与m*n个点( i,p),究竟放那一侧,我选择n个程序在S侧。其实若放T侧,貌似可以直接顺序找到每个程序对应的点( i,p),但还要处理每个程序在内存中的具体时间,复杂度上是相同的。

3、我这样处理其实也存在弊端,这是另一种(n个点在T侧)所能避免的,真亏我能想出来。

  固定内存 i ,查找p,从1找到第一个为0的点之前截止,这些点对应的 left[] 就是放在内存 i 中的程序编号。但可能n个程序都在同一个内存中,所以p的上界要定在(n+1)而不是n;这又引发了另一个问题:若n个程序都在最后一个内存中,所找到的(n+1)对应的点是第(m*n+1)个点,超出了既定的数据范围,若初始化右侧数据只是[1,m*n]的话,(m*n+1)这个点会访问到之前的数据。

 #include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define clr(a,m) memset(a,m,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
using namespace std; const int MAXN=;
const int MAXM=;
const int INF =1e9; struct Point{
int c,t;
Point(){}
Point(int _c,int _t):c(_c),t(_t){}
bool operator < (const Point res)const {
return c<res.c;
}
}; struct Run{
int num,l,r;
Run(){}
Run(int _num,int _l,int _r):num(_num),l(_l),r(_r){}
}run[MAXN];
int time[MAXM]; int mem[MAXM],gap[MAXN][MAXN*MAXM];//数组忘记改大小了
vector<Point>p[MAXN]; int n,m,cnt;
int Lx[MAXN],S[MAXN];
int Ly[MAXN*MAXM],T[MAXN*MAXM],left[MAXN*MAXM],slack[MAXN*MAXM]; void init()
{
rep(i,,n)
p[i].clear();
} void read()
{
init();
rep(i,,m)
scanf("%d",&mem[i]);
rep(i,,n){
int k,c,t;
scanf("%d",&k);
rep(j,,k){
scanf("%d%d",&c,&t);
p[i].push_back(Point(c,t));
}
}
rep(i,,n){
int sz=p[i].size();
rep(j,,m){
int tt;
if(mem[j]<p[i][].c)
tt=INF;
else{
int x=upper_bound(p[i].begin(),p[i].end(),Point(mem[j],))-p[i].begin();
tt=p[i][x-].t;
} rep(p,,n){
if(tt==INF)gap[i][(j-)*n+p]=-INF;
else gap[i][(j-)*n+p]=-p*tt;
}
}
}
} bool match(int u)
{
S[u]=true;
rep(v,,n*m)
if(!T[v]){
int tmp=Lx[u]+Ly[v]-gap[u][v];
if(tmp==){
T[v]=true;
if(!left[v]||match(left[v])){
left[v]=u;
return true;
}
}else slack[v]=min(slack[v],tmp);
}
return false;
} void update()
{
int a=INF;
rep(v,,n*m)//!!
if(!T[v])
if(a>slack[v]){
a=slack[v];
}
rep(i,,n)
if(S[i])Lx[i]-=a;
rep(i,,n*m)//!!
if(T[i])Ly[i]+=a; } void KM()
{
rep(i,,n){
Lx[i]=-INF;
rep(j,,n*m)
if(Lx[i]<gap[i][j]){
Lx[i]=gap[i][j];
}
}
rep(i,,n*m+)
left[i]=Ly[i]=; rep(i,,n){
rep(j,,n*m)
slack[j]=INF;
while()
{
rep(j,,n)
S[j]=;
rep(j,,n*m)
T[j]=;
if(match(i))
break;
else{
update();
}
}
}
} void print()
{
printf("Case %d\n",++cnt); int ans=;
rep(i,,n)
ans+=Lx[i];
rep(i,,n*m)
ans+=Ly[i];
printf("Average turnaround time = %.2f\n",-ans*1.0/n); clr(time,);
rep(i,,m){
int sz;
rep(p,,n+)//!会不会全都在同一个内存区?放在最后一个内存区,找到的+1会越界找到上一组数据
if(left[(i-)*n+p]==){
sz=p-;
break;
}
rrep(p,sz,){
int x=left[(i-)*n+p];
run[x]=Run(i,time[i],time[i]-gap[x][(i-)*n+p]/p);
time[i]-=gap[x][(i-)*n+p]/p;
}
}
rep(i,,n)
printf("Program %d runs in region %d from %d to %d\n",i,run[i].num,run[i].l,run[i].r);
} int main()
{
cnt=;
while(~scanf("%d%d",&m,&n))
{
if(!n&&!m)
return ;
if(cnt)puts("");
read();
KM();
print();
}
return ;
}
/*
2 4
40 60
1 35 4
1 20 3
1 40 10
1 60 7
2 2
20 40
2 20 100 40 2
2 20 100 40 3
*/

UVALive 2238 Fixed Partition Memory Management(二分完美匹配)的更多相关文章

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

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

  2. Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配

    /** 题目: Fixed Partition Memory Management UVALive - 2238 链接:https://vjudge.net/problem/UVALive-2238 ...

  3. LA2238 Fixed Partition Memory Management

    题目大意: m(m<=10)个内存区域,n(n<=50)个程序.找出一个方案来,使得平均结束时刻尽量小.题目保证有解. 同一个程序运行在不同大小的内存区域内,其运行时间不同.(注意,这里说 ...

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

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

  5. UVALive 4043 Ants(二分图完美匹配)

    题意:每个蚁群有自己的食物源(苹果树),已知蚂蚁靠气味辨别行进方向,所以蚁群之间的行动轨迹不能重叠.现在给出坐标系中n个蚁群和n棵果树的坐标,两两配对,实现以上要求.输出的第 i 行表示第 i 个蚁群 ...

  6. UVA 11383 Golden Tiger Claw(最佳二分图完美匹配)

    题意:在一个N*N的方格中,各有一个整数w(i,j),现在要求给每行构造row(i),给每列构造col(j),使得任意w(i,j)<=row(i)+col(j),输出row(i)与col(j)之 ...

  7. Operating System Memory Management、Page Fault Exception、Cache Replacement Strategy Learning、LRU Algorithm

    目录 . 引言 . 页表 . 结构化内存管理 . 物理内存的管理 . SLAB分配器 . 处理器高速缓存和TLB控制 . 内存管理的概念 . 内存覆盖与内存交换 . 内存连续分配管理方式 . 内存非连 ...

  8. Lifetime-Based Memory Management for Distributed Data Processing Systems

    Lifetime-Based Memory Management for Distributed Data Processing Systems (Deca:Decompose and Analyze ...

  9. lwIP Memory Management

    http://lwip.wikia.com/wiki/Lwipopts.h Memory management (RAM usage) /** * MEM_LIBC_MALLOC==1: Use ma ...

随机推荐

  1. C++排序函数sort/qsort使用

    问题描述:        C++排序函数sort/qsort的使用 问题解决:           (1)sort函数使用   注:           sort函数,参数1为数组首地址,参数2是数组 ...

  2. 时隔8年HTML 5终于定稿!

    我们第一次谈论 HTML5 要改变世界大概是因为乔布斯,他坚持在 iOS 上不兼容 Flash,在 Adobe 统治多媒体开发的那个年代,这需要付出极大的勇气.这么多年过去了,虽然所有人都在谈论 HT ...

  3. 【BZOJ】【3275】Numbers

    网络流/最小割 Orz了Jiry_2神犇,蒟蒻网络流建模什么的完全不会啊T_T 按奇偶性来分组实在太巧妙了……然后相关的点之间连边表示只能选其一,来求最小割…… /****************** ...

  4. Matlab中sort函数的使用

    主要看大神们如何使用,先模仿. [~,y] = sort(v),如果v是向量,那么y返回的是v中的下标(不好表达),看下面的,发现y是是下标,对应的是c中元素*(由小到大排序).使用c(y)就得到了由 ...

  5. vs2010中臃肿的ipch和sdf文件

    使用VS2010建立C++解决方案时,会生成SolutionName.sdf和一个叫做ipch的文件夹,这两个文件再加上*.pch等文件使得工程变得非常的庞大,一个简单的程序都会占用几十M的硬盘容量, ...

  6. 【面试题013】在O(1)时间删除链表结点

    [面试题013]在O(1)时间删除链表结点  我们要删除结点i,我们可以把结点i的下一个结点j的内容复制到结点i,然后呢把结点i的指针指向结点j的下一个结点.然后在删除结点j. 1.如果结点i位于链表 ...

  7. HDU2594 Simpsons’ Hidden Talents 字符串哈希

    最近在学习字符串的知识,在字符串上我跟大一的时候是没什么区别的,所以恶补了很多基础的算法,今天补了一下字符串哈希,看的是大一新生的课件学的,以前觉得字符串哈希无非就是跟普通的哈希没什么区别,倒也没觉得 ...

  8. hadoop2.2.0集群搭建与部署

    原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3818908.html 一.安装环境 1.系统环境 CentOS  6.4 2.集群机器节点ip 节点一i ...

  9. Java传入参数个数不确定可用(Type ... values)

    /** * 可变长的参数. * 有时候,我们传入到方法的参数的个数是不固定的,为了解决这个问题,我们一般采用下面的方法: * 1. 重载,多重载几个方法,尽可能的满足参数的个数.显然这不是什么好办法. ...

  10. A. Sorting Railway Cars

    A. Sorting Railway Cars time limit per test 2 seconds memory limit per test 256 megabytes input stan ...