vijos1538 [WC2001]高性能计算机(dp)

黑书1.5.2 例题4高性能计算机
1. 问题有2个子问题:
(1). 计算第x个节点完成i个A任务和j个B任务需要的最短时间.
(2). 前x个节点完成i个A任务和j个B任务, 取所有节点运行时间最大值作为实际运行时间.
解决第一个问题:对节点x,用t[0/1][i][j]表示此节点完成i个A任务和j个B任务,且最后完成的是A(0)B(1)任务需要的最短时间.
则状态转移方程:
t[0][i][j]=min{t[1][i-k][j]+ta[x]+ka[x]*k*k}
t[1][i][j]=min{t[0][i][j-k]+tb[x]+kb[x]*k*k}.
边界条件为t[0][0][0]=t[1][0][0]=0.注意给t清最大值。
再记一个tim[x][i][j]数组,表示第x个节点完成i个A,j个B所需的最短时间。
解决第二个问题:用dp[x][i][j]表示前x个节点完成i个A任务和j个B任务的最短实际运行时间。则
dp[x][i][j] = min{max(dp[x-1][i-ki][j-kj],tim[x][ki][kj])}
边界条件为dp[1][i][j]=tim[1][i][j]。
复杂度为 O(pna2nb2) ,此题还是可以过得。书上还有很高深的优化。。。蒟蒻这里就不介绍了。

#include <cstdio>
#include <cstring>
#define N 21
int na,nb,n,ta[N],tb[N],ka[N],kb[N],tim[N][61][61],dp[N][61][61];
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void calc(int x){
    int t[2][61][61];//0--A,1--B
    memset(t,0x3f,sizeof(t));
    t[1][0][0]=t[0][0][0]=0;
    for(int i=0;i<=na;++i)
        for(int j=0;j<=nb;++j){
            for(int k=1;k<=i;++k) t[0][i][j]=min(t[0][i][j],t[1][i-k][j]+ta[x]+ka[x]*k*k);
            for(int k=1;k<=j;++k) t[1][i][j]=min(t[1][i][j],t[0][i][j-k]+tb[x]+kb[x]*k*k);
            tim[x][i][j]=min(t[0][i][j],t[1][i][j]);
        }
}
int main(){
//  freopen("a.in","r",stdin);
    na=read();nb=read();n=read();
    for(int i=1;i<=n;++i) ta[i]=read(),tb[i]=read(),ka[i]=read(),kb[i]=read();
    for(int i=1;i<=n;++i) calc(i);
    memset(dp,0x3f,sizeof(dp));
    for(int i=0;i<=na;++i)
        for(int j=0;j<=nb;++j)
            dp[1][i][j]=tim[1][i][j];
    for(int x=2;x<=n;++x)
        for(int i=0;i<=na;++i)
            for(int j=0;j<=nb;++j){
                for(int ki=0;ki<=i;++ki)
                    for(int kj=0;kj<=j;++kj)
                        dp[x][i][j]=min(dp[x][i][j],max(dp[x-1][i-ki][j-kj],tim[x][ki][kj]));
            }
    printf("%d\n",dp[n][na][nb]);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值