码迷,mamicode.com
首页 > 其他好文 > 详细

UVA1006 Fixed Partition Memory Management

时间:2020-03-21 16:32:40      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:思路   art   size   getch   return   min   case   code   倒数   

题意:

题目链接
有N个程序需要运行,同一个程序在不同的运行空间大小中运行时间不同(一个程序在2G的内存下运行5s,5G的内存下运行2s .etc)
给出M个运行区域,每个区域有各自的空间,同一时间一个区域只能运行一个程序
求如何安排使得所有程序的结束时间之和最小 N<=10 M<=50
(这样说好像也说不太清楚,其实看样例最好懂了/xyx)

思路:

这道题的建模极为经典
对于一个运行区域,设每个程序依次用时t1,t2....tk
那么这个区域的总用时为ri=kt1+(k-1)t2+....+tk
容易发现,倒数第i个的实际贡献是itk
于是从每一个程序出发向每个运行区域(共n
m个代表这个区域的倒数第若干个运行)连边,边权为序数*程序用时
然后就是一个二分图带权最小匹配了

code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
int m,n;
int mem[15];
int ep1[55],ep2[15][55],lk[55][15][55],match[15][55],slack[15][55],val[15][55];
bool vis1[55],vis2[15][55];
pair<int,int>fm[55];
inline int read()
{
    int s=0,w=1; char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    return s*w;
}
inline void _init()
{
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            for(int k=1;k<=n;++k)
                lk[i][j][k]=-1e9;
    for(int i=1;i<=m;++i)mem[i]=read();
    for(int i=1;i<=n;++i)
    {
        int k=read();
        int pre_s=read(),pre_t=read();
        for(int j=2;j<=k;++j)
        {
            int s=read(),t=read();
            for(int e=1;e<=m;++e)
                if(mem[e]>=pre_s&&mem[e]<s)
                    for(int p=1;p<=n;++p)
                        lk[i][e][p]=-pre_t*p;
            pre_s=s,pre_t=t;
        }
        for(int e=1;e<=m;++e)
            if(mem[e]>=pre_s)
                for(int p=1;p<=n;++p)
                    lk[i][e][p]=-pre_t*p;
    }
}
bool dfs(int x)
{
    vis1[x]=1;
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
        {
            if(vis2[i][j]) continue;
            int gap=ep1[x]+ep2[i][j]-lk[x][i][j];
            if(!gap)
            {
                vis2[i][j]=1;
                if(match[i][j]==-1||dfs(match[i][j]))
                {
                    match[i][j]=x;
                    return true;
                }
            }
            else slack[i][j]=min(slack[i][j],gap);
        }
    return false;
}
inline void KM()
{
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            match[i][j]=-1,ep2[i][j]=0;
    for(int i=1;i<=n;++i)
    {
        ep1[i]=-1e9;
        for(int j=1;j<=m;++j)
            for(int k=1;k<=n;++k)
                ep1[i]=max(ep1[i],lk[i][j][k]);
    }
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
            for(int k=1;k<=n;++k)
                slack[j][k]=1e9;
        while(1)
        {
            for(int j=1;j<=n;++j)vis1[j]=0;
            for(int j=1;j<=m;++j)
                for(int k=1;k<=n;++k)
                    vis2[j][k]=0;
            if(dfs(i)) break;
            int d=1e9;
            for(int j=1;j<=m;++j)
                for(int k=1;k<=n;++k)
                    if(!vis2[j][k])
                        d=min(d,slack[j][k]);
            for(int j=1;j<=n;++j)
                if(vis1[j]) ep1[j]-=d;
            for(int j=1;j<=m;++j)
                for(int k=1;k<=n;++k)
                {
                    if(vis2[j][k]) ep2[j][k]+=d;
                    else slack[j][k]-=d;
                }
        }
    }
}
inline void _print()
{
    int ans=0;
    for(int i=1;i<=n;++i)
        ans-=ep1[i];
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            ans-=ep2[i][j];
    printf("Average turnaround time = %.2f\n",(double)ans/n);
    memset(val,0,sizeof(val));
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            if(match[i][j]!=-1)
            {
                fm[match[i][j]]=make_pair(i,j);
                val[i][j]=lk[match[i][j]][i][j]/j;
            }
    for(int i=1;i<=m;++i)
        for(int j=n-1;j;--j)
            val[i][j]+=val[i][j+1];
    for(int i=1;i<=n;++i)
    {
        int &u=fm[i].first,&v=fm[i].second;
        printf("Program %d runs in region %d from %d to %d\n",i,u,-val[u][v]+lk[i][u][v]/v,-val[u][v]);
    }
    puts("");
}
int main()
{
    for(int q=1;;++q)
    {
        m=read(),n=read();
        if(!m && !n) break;
        _init();KM();
        printf("Case %d\n",q);
        _print(); 
    }
    return 0;
}

代码太丑,巨佬勿喷/xyx

UVA1006 Fixed Partition Memory Management

标签:思路   art   size   getch   return   min   case   code   倒数   

原文地址:https://www.cnblogs.com/zmyzmy/p/12539823.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!