UVALive 2238 Fixed Partition Memory Management 固定分区内存管理(KM算法,变形)
题意:目前有一部分可用内存,分为m个大小固定的区域。现有n个程序要执行,每个程序在不同大小的内存中运行所需的时间不同,要使运行完所有程序所耗时最少,问每个程序在哪块区域中从什么时间运行到什么时间,以及运行完所有程序的平均周转时间。
思路:各种记录有点麻烦!
m个区域看成m台内存大小为该区域大小的计算机,然后n个程序分别要选择在其中一台计算机中运行。由于运行有先后顺序,这也很影响平均周转时间,所以最极端时,其中某台计算机可能有n个程序要运行,那么每台计算机就得有n个位置供挑选。所以一共有n*m个位置啦,而只有n个程序,所以左边有n个点,右边有n*m个点,这样可以用KM算法求最佳匹配(必须最佳),而因为我们要使得周转时间少,所以建图时可以将边取相反数。
例如一台计算机:设有k个程序运行在该机,则其运行时间分别为t1,t2……tk,则第i个程序结束时间Ti=t1+t2+……+ti (因为它得等前面的人运行完),则此机器上所有程序运行时间之和为sum=k*t1 + (k-1)*t2 + (k-2)*t3 + …… + 1*tk。对于倒数第p个执行的程序c来说,其对总运行时间的贡献为p*tc(tc该程序在该机器中所需的运行时间)。其他机器也是这样的。
那么可以建图了,如果程序c能在该机器x上运行,必定有一个运行时间t,而c可能排在任意一个位置,所以c应该有边连到机器x上的任意一个倒数为p的位置,权值为-t*p。这样子求KM的最佳匹配就行了。记得将点数少的放在左边的集合中。
输出才是个技术活!要特别注意的是大小的问题,n<=50,m<=10。
#include <bits/stdc++.h>
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
#define pii pair<int,int>
#define INF 0x7f7f7f7f
#define LL long long
using namespace std;
const int N=;
const int M=;
vector<int> vect[N];
struct node
{
int from, to, w;
node(){};
node(int from,int to,int w ):from(from),to(to),w(w){};
}edge[N*M*M]; struct node1
{
int region; //第几个区域
int countdown; //倒数第几
node1(){};
node1(int re,int cd ):region(re),countdown(cd){};
}pos[N*M] ; int edge_cnt, pos_cnt;
int m, n;
int msize[N]; //m块区域
int k[N], req[N][M][]; //m个程序的要求 void add_edge(int from,int to,int w)
{
edge[edge_cnt]=node(from, to, w);
vect[from].push_back(edge_cnt++);
}
void add_pos(int r,int cd)
{
pos[pos_cnt]=node1(r,cd);
pos_cnt++;
} int Lx[N], Ly[N*M], slack[N*M];
int girl[N*M], S[N], T[N*M];
int get_time(int p,int siz) //在reg区域找到能运行siz大小内存的时间
{
int t=;
for(int r=; r<=k[p]; r++)
{
if( siz>=req[p][r][] ) t=req[p][r][];
else break;
}
return t;
}
int last[N][M]; void build()
{
//共n*m个位置.
for(int j=; j<=m; j++) //对于每块区域
for(int r=; r<=n; r++) //每个位置(倒数的)
add_pos(j, r); for(int i=; i<=n; i++) //每个程序
{
for(int j=; j<=m; j++) //每块区域
{
int t=get_time(i, msize[j] );
if(!t) continue; //此程序不可在此区域运行。
for(int r=; r<=n; r++) //每个位置
add_edge(i, (j-)*n+r, -t*r );
last[i][j]=t; //记录i程序在第j区域中的运行时间
}
}
} bool DFS(int x)
{
S[x]=true;
for(int j=; j<vect[x].size(); j++)
{
node &e=edge[vect[x][j]];
if(T[e.to]) continue; int tmp=Lx[x] +Ly[e.to] -e.w;
if(tmp==)
{
T[e.to]=true;
if(!girl[e.to] || DFS( girl[e.to] ) )
{
girl[e.to]=x;
return true;
}
}
else if(slack[e.to]>tmp) slack[e.to]=tmp;
}
return false;
} void KM() //用n个程序,匹配n*m个位置
{
//初始化
memset(girl, , sizeof(girl));
memset(Ly, , sizeof(Ly)); //数量比较大
for(int i=; i<=n; i++)
{
Lx[i]=-INF;
for(int j=; j<vect[i].size(); j++) //n*m个位置要匹配
{
node &e=edge[vect[i][j]];
Lx[i]=max(Lx[i], e.w ); //取最大的一条边
}
} for(int i=; i<=n; i++)
{
for(int j=n*m; j>; j--) slack[j]=INF;
while(true)
{
memset(T, , sizeof(T));
memset(S, , sizeof(S));
if(DFS(i)) break; //找最小slack
int d=INF;
for(int j=; j<pos_cnt; j++)
if(!T[j] && d>slack[j])
d=slack[j]; //更新S
for(int j=; j<=n; j++)
if(S[j]) Lx[j]-=d; //更新T
for(int j=; j<pos_cnt; j++)
if(T[j]) Ly[j]+=d;
else slack[j]-=d;
}
}
} inline int cmp(pii a, pii b){return a.second>b.second;}
int program[N][];
vector<pii> region[M];
void print(int Case)
{
memset(program, , sizeof(program));
for(int i=; i<=m; i++) region[i].clear(); for(int i=; i<pos_cnt; i++) //将匹配对的信息绑定在一起
if(girl[i]!=)
region[ pos[i].region ].push_back(make_pair( girl[i], pos[i].countdown )); for(int i=; i<=m; i++) //排个序,先执行的在前
sort(region[i].begin(), region[i].end(), cmp); double sum=0.0;
for(int i=; i<=m; i++) //计算执行的时间
{
int now=;
for(int j=; j<region[i].size(); j++)
{ pii a=region[i][j];
program[a.first][]=i; program[a.first][]=now;
now+=last[a.first][i]; //所需要的时间呢?
program[a.first][]=now; sum+=now; //累加时间
}
} if(Case>) printf("\n");
printf("Case %d\n", Case);
printf("Average turnaround time = %.2f\n", sum/n);
for(int i=; i<=n; i++)
{
printf("Program %d runs in region %d from %d to %d\n", i, program[i][], program[i][], program[i][] );
}
} int main()
{
freopen("input.txt", "r", stdin);
int Case=;
while(scanf("%d%d",&m,&n), n+m)
{
edge_cnt=pos_cnt=;
for(int i=; i<=n; i++) vect[i].clear(); for(int i=; i<=m; i++) scanf("%d", &msize[i]); //m个区域的大小
for(int i=; i<=n; i++) //程序i的内存要求,及时间。
{
scanf("%d", &k[i]);
for(int j=; j<=k[i]; j++)
scanf("%d %d", &req[i][j][], &req[i][j][]);
}
build(); //建图
KM(); //最佳匹配
print(++Case);//输出
}
return ;
}
AC代码
UVALive 2238 Fixed Partition Memory Management 固定分区内存管理(KM算法,变形)的更多相关文章
- UVALive 2238 Fixed Partition Memory Management(二分完美匹配)
题意:计算机中有一些固定大小的内存,内存越大,处理速度越快.对于一个程序,加入不同的内存空间,处理所需时间不同.现给出m个内存空间,n个程序,对于每个程序程序,有k组数据(s,t),分别表示当程序 i ...
- Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配
/** 题目: Fixed Partition Memory Management UVALive - 2238 链接:https://vjudge.net/problem/UVALive-2238 ...
- LA2238 Fixed Partition Memory Management
题目大意: m(m<=10)个内存区域,n(n<=50)个程序.找出一个方案来,使得平均结束时刻尽量小.题目保证有解. 同一个程序运行在不同大小的内存区域内,其运行时间不同.(注意,这里说 ...
- 【LA2238 训练指南】固定分区内存管理 【二分图最佳完美匹配,费用流】
题意 早期的多程序操作系统常把所有的可用内存划分为一些大小固定的区域,不同的区域一般大小不同,而所有区域的大小之和为可用内存的大小.给定一些程序,操作系统需要给每个程序分配一个区域,使得他们可以同时执 ...
- UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配,KM算法)
题意: 有n个蚂蚁n棵树,蚂蚁与树要配对,在配对成功的一对之间连一条线段,要求所有线段不能相交.按顺序输出蚂蚁所匹配的树. 思路: 这个题目真是技巧啊,不能用贪心来为每个蚂蚁选择最近的树,这样很可能是 ...
- Memory Management in Open Cascade
Open Cascade中的内存管理 Memory Management in Open Cascade eryar@163.com 一.C++中的内存管理 Memory Management in ...
- 如何展开Linux Memory Management学习?
Linux的进程和内存是两座大山,没有翻过这两座大山对于内核的理解始终是不完整的. 关于Linux内存管理,在开始之前做些准备工作. 首先bing到了Quora的<How can one rea ...
- Operating System Memory Management、Page Fault Exception、Cache Replacement Strategy Learning、LRU Algorithm
目录 . 引言 . 页表 . 结构化内存管理 . 物理内存的管理 . SLAB分配器 . 处理器高速缓存和TLB控制 . 内存管理的概念 . 内存覆盖与内存交换 . 内存连续分配管理方式 . 内存非连 ...
- Lifetime-Based Memory Management for Distributed Data Processing Systems
Lifetime-Based Memory Management for Distributed Data Processing Systems (Deca:Decompose and Analyze ...
随机推荐
- 并不对劲的p4449于神之怒加强版
题目大意 给定\(t,k(t\leq2000,k\leq5*10^6)\) \(t\)组询问,每组给出\(n,m(n,m\leq5*10^6)\)求$\sum_{i=1}^n \sum_{j=1}^m ...
- BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS
BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N ...
- fastText(二):微博短文本下fastText的应用(一)
众所周知,微博中的内容以短文本居多,文本内容随意性极强,这给建模增加了很大的难度.针对这一问题,这里分享一下fastText在微博短文本的应用. 任务目标简单介绍一下整个任务的目标:给微博内容打上标签 ...
- Collection View Programming Guide for iOS---(五)---Incorporating Gesture Support
Incorporating Gesture Support 结合手势支持 You can add greater interactivity to your collection views th ...
- 网络爬虫之Selenium模块和Xpath表达式+Lxml解析库的使用
实际生产环境下,我们一般使用lxml的xpath来解析出我们想要的数据,本篇博客将重点整理Selenium和Xpath表达式,关于CSS选择器,将另外再整理一篇! 一.介绍: selenium最初是一 ...
- linux中vfork对打开文件的处理
vfork和fork fork()函数是拷贝一个父进程的副本,拥有独立的代码段 数据段 堆栈空间 然而vfork是共享父亲进程的代码以及代码段 vfork是可以根据需要复制父进程空间,这样很大程度的提 ...
- 任务20:DI初始化的源码解读 & 任务21:依赖注入的使用
20 我们来看一下asp.net core中依赖注入的源码 https://github.com/aspnet/AspNetCore/tree/master/src/Hosting 任务21:依赖注入 ...
- (水题)Codeforces - 650A - Watchmen
http://codeforces.com/contest/650/problem/A 一开始想了很久都没有考虑到重复点的影响,解欧拉距离和曼哈顿距离相等可以得到 $x_i=x_j$ 或 $y_i=y ...
- lightoj 1033【区间DP/LCS】
题意: 给你一个长度<=100的字符串. 然后你可以在任何位置插入字符,问最少插入几个构成回文. 思路: 1.长度-LCS: 2.区间DP; 我保证小的区间是一个回文,然后枚举区间,构成大区间, ...
- 当打开一个.h或.cpp文件时, Solution Explorer就自动展开文件所在的目录
当打开一个.h或.cpp文件时, Solution Explorer就自动展开文件所在的目录: 如果不想展开: Tools -> Options -&g ...