【LA2238 训练指南】固定分区内存管理 【二分图最佳完美匹配,费用流】

题意

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

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

分析

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

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

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

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

 

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

  

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <queue>
  6 
  7 using namespace std;
  8 const int maxn=6000+10;
  9 const int maxm=100000+10;
 10 const int INF=1e9;
 11 struct MCMF{
 12     int head[maxn],to[maxm],Next[maxm],from[maxm],flow[maxm],cap[maxm];
 13     long long cost[maxm];
 14     int n,m,s,t,sz;
 15     int inq[maxn];
 16     int d[maxn];
 17     int p[maxn];
 18     int a[maxn];
 19 
 20     void init(int n){
 21         this->n=n;
 22         sz=-1;
 23         memset(head,-1,sizeof(head));
 24     }
 25     void AddEdge(int a,int b,int ca,long long co){
 26         ++sz;
 27         to[sz]=b,from[sz]=a,Next[sz]=head[a],head[a]=sz;
 28         flow[sz]=0,cap[sz]=ca,cost[sz]=co;
 29         ++sz;
 30         to[sz]=a,from[sz]=b,Next[sz]=head[b],head[b]=sz;
 31         flow[sz]=ca,cap[sz]=ca,cost[sz]=-co;
 32     }
 33     bool BellmanFord(int s,int t,int &Flow,long long &Cost){
 34         for(int i=0;i<=n;i++)d[i]=INF;
 35         memset(inq,0,sizeof(inq));
 36         d[s]=0;inq[s]=1;p[s]=-1;a[s]=INF;
 37         queue<int>Q;
 38         Q.push(s);
 39         while(!Q.empty()){
 40             int u=Q.front();Q.pop();
 41             inq[u]=0;
 42             for(int i=head[u];i!=-1;i=Next[i]){
 43                 int v=to[i];
 44                 if(cap[i]>flow[i]&&d[v]>d[u]+cost[i]){
 45                     d[v]=d[u]+cost[i];
 46                     p[v]=i;
 47                     a[v]=min(a[u],cap[i]-flow[i]);
 48                     if(!inq[v]){
 49                         Q.push(v);
 50                         inq[v]=1;
 51                     }
 52                 }
 53             }
 54         }
 55         if(d[t]==INF)return false;
 56         Flow+=a[t];
 57         Cost+=(long long)d[t]*(long long)a[t];
 58         int u=t;
 59 
 60         while(u!=s){
 61             flow[p[u]]+=a[t];
 62             flow[p[u]^1]-=a[t];
 63             u=from[p[u]];
 64         }
 65         return true;
 66     }
 67 
 68     long long Mincost(int s,int t){
 69         int Flow=0;
 70         long long Cost=0;
 71         while(BellmanFord(s,t,Flow,Cost));
 72         return Cost;
 73     }
 74 }mcmf;
 75 const int maxN=100;
 76 const int maxM=100;
 77 int n,m,kase;
 78 int Size[maxM];
 79 int p[maxN][maxN],tim[maxN][maxN],Time[maxN];
 80 int main(){
 81     kase=0;
 82     while(scanf("%d%d",&m,&n)!=EOF&&(n||m)){
 83         if(kase){
 84           printf("\n");
 85         }
 86 
 87         ++kase;
 88         for(int i=1;i<=m;i++)
 89             scanf("%d",&Size[i]);
 90         for(int i=1;i<=n;i++){
 91             scanf("%d",&p[i][0]);
 92             for(int j=1;j<=p[i][0];j++){
 93                 scanf("%d%d",&p[i][j],&tim[i][j]);
 94             }
 95         }
 96         mcmf.init(n+n*m+3);
 97         for(int i=1;i<=n;i++){
 98             for(int j=1;j<=m;j++){
 99                     if(p[i][1]>Size[j])continue;
100                     int T=INF;
101                     for(int l=1;l<=p[i][0];l++){
102                         if(p[i][l]<=Size[j]){
103                             T=min(T,tim[i][l]);
104                         }
105                     }
106                 for(int l=1;l<=n;l++){
107                     mcmf.AddEdge(i,j*n+l,1,l*T);
108                 }
109             }
110         }
111         for(int i=1;i<=n;i++)
112             mcmf.AddEdge(0,i,1,0);
113         for(int i=n+1;i<=n*m+n;i++)
114             mcmf.AddEdge(i,n*m+n+1,1,0);
115         long long res=mcmf.Mincost(0,n*m+n+1);
116         double ans=(double)res/n;
117         printf("Case %d\n",kase);
118         printf("Average turnaround time = %.2f\n",ans);
119 
120         int ANS[maxN][maxN],bel[maxN];
121         memset(ANS,-1,sizeof(ANS));
122         memset(Time,0,sizeof(Time));
123         for(int i=1;i<=n;i++){
124             for(int j=mcmf.head[i];j!=-1;j=mcmf.Next[j]){
125                 if(j%2)continue;
126                 if(mcmf.cap[j]>mcmf.flow[j])continue;
127                 int v=mcmf.to[j];
128                 int a=v/n,b=v%n;
129                 if(b==0){
130                     b=n;
131                     a--;
132                 }
133                 ANS[a][b]=i;
134                 bel[i]=a;
135                 Time[i]=mcmf.cost[j]/b;
136             }
137         }
138         int F[maxN],T[maxN];
139         for(int i=1;i<=m;i++){
140             int st=0;
141             for(int j=n;j>=1;j--){
142                 if(ANS[i][j]!=-1){
143                     st=j;
144                     break;
145                 }
146             }
147             int all=0;
148             for(int j=st;j>=1;j--){
149                 int x=ANS[i][j];
150                 F[x]=all,T[x]=all+Time[x];
151                 all=T[x];
152             }
153         }
154 
155         for(int i=1;i<=n;i++){
156             printf("Program %d runs in region %d from %d to %d\n",i,bel[i],F[i],T[i]);
157         }
158     }
159 return 0;
160 }
View Code

 

  

posted @ 2018-07-13 18:44  蒟蒻LQL  阅读(287)  评论(0编辑  收藏  举报