• Luogu P2066 机器分配(dp)


    P2066 机器分配

    题面

    题目背景

    题目描述

    总公司拥有高效设备 (M) 台,准备分给下属的 (N) 个分公司。各分公司若获得这些设备,可以为国家提供一定的盈利。问:如何分配这 (M) 台设备才能使国家得到的盈利最大?求出最大盈利值。其中 (M leq 15, N leq 10) 。分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数 (M)

    输入输出格式

    输入格式:

    第一行有两个数,第一个数是分公司数 (N) ,第二个数是设备台数 (M)

    接下来是一个 (N*M) 的矩阵,表明了第 (I) 个公司分配 (J) 台机器的盈利。

    输出格式:

    (1) 行为最大盈利值

    (2) 到第 (n) 为第 (i) 分公司分 (x)

    (P.S.) 要求答案的字典序最小

    输入输出样例

    输入样例:

    3 3
    30 40 50
    20 30 50
    20 25 30
    

    输出样例:

    70
    1 1
    2 1
    3 1
    

    思路

    设计 (dp[i]) 表示分配 (i) 台机器后能获得的最大盈利,定义 (a[i][j])(i) 公司在得到 (j) 台机器后能获得的利益,那么就有:

    [dp[i]=max { dp[i-k]+a[j][k](j in [1,n],i in [1,m]) } ]

    代码实现的话可以这样写:

    for(int i=1;i<=n;i++)
        for(int j=m;j>=0;j--)
            for(int k=j;k>=0;k--)
                dp[j]=max(dp[j],dp[j-k]+a[i][k]);
    

    这样我们就能解决第一个问题。

    那如何解决第二个问题呢?我们可以再定义一个变量 (way[i][j]) 表示分配出 (i) 台机器并得到最优解时第 (j) 家公司应该被分配 (way[i][j]) 台机器,那么每当 (dp[i]) 被更新时我们就需要来更新 (way)

    for(int i=1;i<=n;i++)
        for(int j=m;j>=0;j--)
            for(int k=j;k>=0;k--)
                if(dp[j]<dp[j-k]+a[i][k])
                    dp[j]=dp[j-k]+a[i][k],way[j][i]=k;
    

    等会!题目还有一个要求我们没有管:

    (P.S.) 要求答案的字典序最小

    实际上,我们这样更新时,因为是从前往后更新,所以本身就是按照字典序来更新的,所以就不用再管了。而得到题目要求的解时,我们就可以这样操作了:

    for(int i=n;i;i--) ans[i]=way[m][i],m-=way[m][i];
    

    接下来输出 (ans) 数组就好啦。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,a[20][20],dp[20],way[20][20],ans[20];
    int read()
    {
        int re=0;
        char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=read();
        for(int i=1;i<=n;i++)
            for(int j=m;j>=0;j--)
                for(int k=j;k>=0;k--)
                    if(dp[j]<dp[j-k]+a[i][k])
                        dp[j]=dp[j-k]+a[i][k],way[j][i]=k;
        printf("%d",dp[m]);
        for(int i=n;i;i--) ans[i]=way[m][i],m-=way[m][i];
        for(int i=1;i<=n;i++) printf("
    %d %d",i,ans[i]);
        return 0;
    }
    
  • 相关阅读:
    C++ generic tools -- from C++ Standard Library
    18 12 18 给服务器添加logging 日志功能
    18 12 14 python提高 装饰器
    18 12 `12 WSGI 协议
    18 12 07 MySQL 与python 的交互
    转 SQL 的数据库 架构规范 之 58到家数据库30条军规解读
    18 12 06 sql 的 基本语句 查询 条件查询 逻辑运算符 模糊查询 范围查询 排序 聚合函数 分组 分页 连接查询 自关联 子查询
    18 12 4 SQL 的基本 语法
    clion 的 安装 变量配置的 搬运工(有点基础应该能看 大家看不懂 就是我自己看 哈哈哈哈哈哈)
    18 11 27 高级的服务器连接 epoll
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9736597.html
Copyright © 2020-2023  润新知