luoguP2066 机器分配 题解

来源:互联网 发布:淘宝下拉菜单小图标 编辑:程序博客网 时间:2024/06/10 18:00

题目

题目描述

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

输入输出格式

输入格式:
第一行有两个数,第一个数是分公司数N,第二个数是设备台数M。

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

输出格式:
第1行为最大盈利值

第2到第n为第i分公司分x台

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

输入输出样例

输入样例#1:
3 3
30 40 50
20 30 50
20 25 30
输出样例#1:
70
1 1
2 1
3 1

分析

显然是一个经典的dp题目。我们定义一个数组:f[i][j]表示前i个公司分配j台机器的最大盈利。那么求解f[i][j]的过程应该怎么求解呢?首先,我们在给第i个公司分配机器的时候,我们肯定为第i-1个公司分配过机器了,所以显然,i的状态由j的状态推导而来,那么我们需要怎么枚举呢?就是:通过枚举i个公司需要多少台机器,再枚举i-1个公司需要多少机器,再找出最大值就可以了。下面上代码:

代码

#include<bits/stdc++.h>using namespace std;inline int read(){    int num=0;    char c=getchar();    for(;c<'0'||c>'9';c=getchar());    for(;c>='0'&&c<='9';c=getchar())num=num*10+c-'0';    return num;}//快读 int n,m,f[30][30],value[30][30],maxl;/*以上是变量说明阶段。f数组:f[i][j]表示前i个公司分j台机器的最大盈利value数组:value[i][j]表示第i个公司分j台机器的盈利*/ int print(int i,int j){    if(i==0)return 0;    for(int k=0;k<=j;k++)    //k枚举了前i-1个分公司分得多少机器     if(maxl==f[i-1][k]+value[i][j-k])    //知道结果倒推回去     {        maxl=f[i-1][k];//步步为营的方式         print(i-1,k);//继续低柜求解         printf("%d %d\n",i,j-k);//倒序输出         break;//搜到了直接跳出循环     }}int main(){    n=read();    m=read();    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    value[i][j]=read();    //读入各种数据     for(int i=1;i<=n;i++)//枚举公司数     for(int j=1;j<=m;j++)//枚举机器数(总)     {        maxl=0;        for(int k=0;k<=j;k++)//枚举前i-1个公司分到的机器数         if(f[i-1][k]+value[i][j-k]>maxl)        /*f[i-1][k]:前i-1个公司分k台机器的利润        value[i][j-k]:第i个公司分j-k台机器的利润        加起来是i个公司分j台机器的最大利润*/         maxl=f[i-1][k]+value[i][j-k];        f[i][j]=maxl;    }    printf("%d\n",f[n][m]);//输出结果     print(n,m);//输出分配方案     return 0;}
原创粉丝点击