• 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。

      1 #include <bits/stdc++.h>
      2 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
      3 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
      4 #define pii pair<int,int>
      5 #define INF 0x7f7f7f7f
      6 #define LL long long
      7 using namespace std;
      8 const int N=60;
      9 const int M=20;
     10 vector<int> vect[N];
     11 struct node
     12 {
     13     int from, to, w;
     14     node(){};
     15     node(int from,int to,int w ):from(from),to(to),w(w){};
     16 }edge[N*M*M];
     17 
     18 struct node1
     19 {
     20     int region;         //第几个区域
     21     int countdown;      //倒数第几
     22     node1(){};
     23     node1(int re,int cd ):region(re),countdown(cd){};
     24 }pos[N*M] ;
     25 
     26 int edge_cnt, pos_cnt;
     27 int m, n;
     28 int msize[N];  //m块区域
     29 int k[N], req[N][M][2];  //m个程序的要求
     30 
     31 
     32 void add_edge(int from,int to,int w)
     33 {
     34     edge[edge_cnt]=node(from, to, w);
     35     vect[from].push_back(edge_cnt++);
     36 }
     37 void add_pos(int r,int cd)
     38 {
     39     pos[pos_cnt]=node1(r,cd);
     40     pos_cnt++;
     41 }
     42 
     43 int Lx[N], Ly[N*M], slack[N*M];
     44 int girl[N*M], S[N], T[N*M];
     45 int get_time(int p,int siz)       //在reg区域找到能运行siz大小内存的时间
     46 {
     47     int t=0;
     48     for(int r=1; r<=k[p]; r++)
     49     {
     50         if( siz>=req[p][r][0] )    t=req[p][r][1];
     51         else break;
     52     }
     53     return t;
     54 }
     55 int last[N][M];
     56 
     57 void build()
     58 {
     59     //共n*m个位置.
     60     for(int j=1; j<=m; j++) //对于每块区域
     61         for(int r=1; r<=n; r++) //每个位置(倒数的)
     62             add_pos(j, r);
     63 
     64 
     65     for(int i=1; i<=n; i++)     //每个程序
     66     {
     67         for(int j=1; j<=m; j++) //每块区域
     68         {
     69             int t=get_time(i, msize[j] );
     70             if(!t)  continue;   //此程序不可在此区域运行。
     71             for(int r=1; r<=n; r++) //每个位置
     72                 add_edge(i, (j-1)*n+r, -t*r );
     73             last[i][j]=t;           //记录i程序在第j区域中的运行时间
     74         }
     75     }
     76 }
     77 
     78 
     79 bool DFS(int x)
     80 {
     81     S[x]=true;
     82     for(int j=0; j<vect[x].size(); j++)
     83     {
     84         node &e=edge[vect[x][j]];
     85         if(T[e.to]) continue;
     86 
     87         int tmp=Lx[x] +Ly[e.to] -e.w;
     88         if(tmp==0)
     89         {
     90             T[e.to]=true;
     91             if(!girl[e.to] || DFS( girl[e.to] ) )
     92             {
     93                 girl[e.to]=x;
     94                 return true;
     95             }
     96         }
     97         else if(slack[e.to]>tmp)    slack[e.to]=tmp;
     98     }
     99     return false;
    100 }
    101 
    102 
    103 void KM()    //用n个程序,匹配n*m个位置
    104 {
    105     //初始化
    106     memset(girl, 0, sizeof(girl));
    107     memset(Ly, 0, sizeof(Ly));  //数量比较大
    108     for(int i=1; i<=n; i++)
    109     {
    110         Lx[i]=-INF;
    111         for(int j=0; j<vect[i].size(); j++) //n*m个位置要匹配
    112         {
    113             node &e=edge[vect[i][j]];
    114             Lx[i]=max(Lx[i], e.w ); //取最大的一条边
    115         }
    116     }
    117 
    118     for(int i=1; i<=n; i++)
    119     {
    120         for(int j=n*m; j>0; j--) slack[j]=INF;
    121         while(true)
    122         {
    123             memset(T, 0, sizeof(T));
    124             memset(S, 0, sizeof(S));
    125             if(DFS(i))  break;
    126 
    127             //找最小slack
    128             int d=INF;
    129             for(int j=1; j<pos_cnt; j++)
    130                 if(!T[j] && d>slack[j])
    131                     d=slack[j];
    132 
    133             //更新S
    134             for(int j=1; j<=n; j++)
    135                 if(S[j])    Lx[j]-=d;
    136 
    137             //更新T
    138             for(int j=1; j<pos_cnt; j++)
    139                 if(T[j])  Ly[j]+=d;
    140                 else      slack[j]-=d;
    141         }
    142     }
    143 }
    144 
    145 inline int cmp(pii a, pii b){return a.second>b.second;}
    146 int program[N][3];
    147 vector<pii> region[M];
    148 void print(int Case)
    149 {
    150     memset(program, 0 , sizeof(program));
    151     for(int i=0; i<=m; i++) region[i].clear();
    152 
    153     for(int i=1; i<pos_cnt; i++)    //将匹配对的信息绑定在一起
    154         if(girl[i]!=0)
    155             region[ pos[i].region ].push_back(make_pair( girl[i],  pos[i].countdown ));
    156 
    157     for(int i=1; i<=m; i++)         //排个序,先执行的在前
    158         sort(region[i].begin(), region[i].end(), cmp);
    159 
    160     double sum=0.0;
    161     for(int i=1; i<=m; i++) //计算执行的时间
    162     {
    163         int now=0;
    164         for(int j=0; j<region[i].size(); j++)
    165         {
    166 
    167             pii a=region[i][j];
    168             program[a.first][0]=i;
    169 
    170             program[a.first][1]=now;
    171             now+=last[a.first][i];       //所需要的时间呢?
    172             program[a.first][2]=now;
    173 
    174             sum+=now;   //累加时间
    175         }
    176     }
    177 
    178     if(Case>1)  printf("
    ");
    179     printf("Case %d
    ", Case);
    180     printf("Average turnaround time = %.2f
    ", sum/n);
    181     for(int i=1; i<=n; i++)
    182     {
    183         printf("Program %d runs in region %d from %d to %d
    ", i, program[i][0], program[i][1], program[i][2] );
    184     }
    185 }
    186 
    187 int main()
    188 {
    189     freopen("input.txt", "r", stdin);
    190     int Case=0;
    191     while(scanf("%d%d",&m,&n), n+m)
    192     {
    193         edge_cnt=pos_cnt=1;
    194         for(int i=0; i<=n; i++) vect[i].clear();
    195 
    196 
    197         for(int i=1; i<=m; i++)    scanf("%d", &msize[i]);   //m个区域的大小
    198         for(int i=1; i<=n; i++) //程序i的内存要求,及时间。
    199         {
    200             scanf("%d", &k[i]);
    201             for(int j=1; j<=k[i]; j++)
    202                 scanf("%d %d", &req[i][j][0], &req[i][j][1]);
    203         }
    204         build();    //建图
    205         KM();    //最佳匹配
    206         print(++Case);//输出
    207     }
    208     return 0;
    209 }
    AC代码
  • 相关阅读:
    UESTC--1727
    css3制作左右拉伸动画菜单
    Mysql主从数据库(master/slave),实现读写分离
    阿里云Centos7.6上面部署基于redis的分布式爬虫scrapy-redis将任务队列push进redis
    利用基于Go Lang的Hugo配合nginx来打造属于自己的纯静态博客系统
    Centos7.6上利用docker搭建Jenkins来自动化部署Django项目
    使用基于Vue.js和Hbuilder的混合模式移动开发打造属于自己的移动app
    Centos7.6上部署Supervisor来监控和操作各类服务
    Centos上配置nginx+uwsgi+负载均衡配置
    Websocket---认识篇
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4734050.html
Copyright © 2020-2023  润新知