题目描述
某总公司拥有高效生产设备M台,准备分给下属的N个分公司。各分公司若获得这些设备,可以为总公司提供一定的盈利。问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值。 分配原则:每个公司有权获得任意数目的设备,但总台数不得超过总设备数M。其中M<=100,N<=100。
输入
第一行为两个整数M,N。接下来是一个N×M的矩阵,其中矩阵的第i行的第j列的数Aij表明第i个公司分配j台机器的盈利。所有数据之间用一个空格分隔。
输出
只有一个数据,为总公司分配这M台设备所获得的最大盈利。
样例输入
3 2
1 2 3
2 3 4
样例输出
4
解题思路
解法一(线性dp):每个公司只能选一种分配方式,使用线性dp,前 i 个公司分配 j 个机器的最大利润等于前i-1个公司的各种状态下分配给第i个公司k个机器的最大值。
解法二(分组背包):第k个公司分i台机器当成物品,那么一共有n*m个物品。一个公司的分配1-m台机器的m种情况当成一组物品,这一组物品相互排斥,要么选一个要么不选,符合分组背包的特点。分i台机器,消耗i个体积,获得的价值就是公司盈利,背包容量就是总共的m台机器。这里提供一维和二维两种存dp的代码。
解法一代码
#include<cstdio>
#include<iostream>
using namespace std;
int a[110][110];
int f[110][110];//f表示前i个公司分配j个机器所获得的最大利益
int main()
{
int m,n,i,j,k;//k表示给第i个公司分配k个机器
scanf("%d%d",&m,&n);
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
scanf("%d",&a[i][j]);
}
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
for(k=0;k<=j;++k)//由哪种状态分配给第i公司k个机器,使得前i个公司分配得到j个机器f[i][j]的值最大
{
if(f[i-1][j-k]+a[i][k]>f[i][j])
f[i][j]=f[i-1][j-k]+a[i][k];
}
}
}
printf("%d",f[n][m]);
return 0;
}
解法二代码1(1维数组存最大价值,可以先看下面2维的理解一下):
#include <iostream>
#include <cstdio>
using namespace std;
bool vist[110][110];
int main()
{
int n,m,i,j;//m台机器表示背包容量
int v[101][101]={0};//每个公司分几个机器的利益表示物品价值
int dp[110]={0};//这里初始化的时候 int p[110]={};括号里不写值是不对的!!
scanf("%d%d",&m,&n);
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
scanf("%d",&v[i][j]);//i件物品的价值
}
int k;//k组,一个公司一组
for(k=1;k<=n;++k)
for(j=m;j>=0;--j)//前【k】个公司分【j】个机器 j相当于体积v
for(i=0;i<=m;++i)//给第k个公司分i个机器,i属于组k
if(j>=i && dp[j]< dp[j-i]+v[k][i])//前k-1个公司要少分i个机器,才能给第k个公司分配i个机器
dp[j]=dp[j-i]+v[k][i];
printf("%d",dp[m]);
return 0;
}
解法二代码2(2维数组存最大价值):
我写的有错误,求大神们找bug。。。。
终于找到bug了,数组v定义的时候应该开>100的,因为我的数组从v【1,1】开始的。。。
#include <iostream>
#include <cstdio>
using namespace std;
int v[110][110]={0}; //v表示价值
int dp[110][110]={0};
int main()
{
int n,m,i,j;//m表示背包容量
scanf("%d%d",&m,&n);
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
scanf("%d",&v[i][j]);//i件物品的价值
}
int k;
for(k=1;k<=n;++k)
for(j=m;j>=0;--j)
{
int temp=dp[k-1][j];
for(i=0;i<=j;++i)
{
if(dp[k-1][j-i]+v[k][i]>temp)
temp = dp[k-1][j-i]+v[k][i];
}
dp[k][j]=temp;
}
printf("%d",dp[n][m]);
return 0;
}