P2066 机器分配 记忆化搜索

185 阅读1分钟

题目链接

P2066 机器分配
题目大意:m台机器分配给n个公司,每个公司在拥有不同的机器数量时可以获得相应的盈利,求出如何分配可获得最大利润。

思路

记忆化搜索,每次枚举第x个公司分配的机器数目。 本题难点在于每个公司分配的台数
刚开始做的时候我只用一个一维数组ans[N],用ans[i]记录第i个公司分配多少机器,每次搜到一个较大值就更新一下。但这样是不可行的,因为第i个公司取到最大值时不一定是全局的最优解。所以不能直接用它作为答案。
考虑用ans[i][j]来记录第i个公司还剩下j台机器可以被分配时可获得的最大利润,这样就可以在最后递归输出答案。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,m,a[N][N],f[N][N],ans[N][N];
inline int read()
{
	int ret=0,flag=1;char ch=getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-')flag=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9')ret=ret*10+ch-'0',ch=getchar();
	return ret*flag;
}
int dfs(int x,int res)
{
	if(f[x][res])return f[x][res];
	if(!res)return 0;
	if(x==n)
	{
		return a[x][res];
	}
	int ret=0;
	for(int i=0;i<=res;++i)
	{
		int me=a[x][i];
		int tmp=dfs(x+1,res-i)+me;
		if(tmp>ret)
		{
			ret=tmp;
			ans[x][res]=i;
		}
	}
	return f[x][res]=ret;
}
void print(int x,int res)
{
	if(x==n)
	{	
		cout<<n<<" "<<res<<endl;
		return;
	}
	cout<<x<<" "<<ans[x][res]<<endl;
	print(x+1,res-ans[x][res]);
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			a[i][j]=read();
		}
	}
	cout<<dfs(1,m)<<endl;
	print(1,m);
}