开始填补今年清北的坑,,,
定义a[i][j]是给前i个公司分配j台机器产生的最大收益
根据mzx老(da)师(lao)所讲,动规题先写爆搜
可以定义一个f[i][j]来存储ans已达到记忆化的效果
这样状态转移方程就得出来了
f[i][j]可以由前一个状态f[i-1][k],k枚举一下前i-1个公司分配k个的情况
其实就是个01背包,,
不过这题还有一个问题就是怎样输出方案
这里用的办法是:查找目标状态由哪个状态递推而来然后向后退(也是根据状态转移方程)
定义a[i][j]是给前i个公司分配j台机器产生的最大收益
根据mzx老(da)师(lao)所讲,动规题先写爆搜
int dfs(int i,int j)//给前i个公司分配j台机器的最收益
{
if(i==0||j==0) return 0;
int ans=0;
if(f[i[[j]!=-1) return f[i][j];
for(int k=0;k<=j;k++)
ans=max(ans,a[i][k]+dfs(i-1,j-k);
return ans;
}
可以定义一个f[i][j]来存储ans已达到记忆化的效果
这样状态转移方程就得出来了
f[i][j]=max(f[i][j],a[i][k]+f[i-1][j-k];
f[i][j]可以由前一个状态f[i-1][k],k枚举一下前i-1个公司分配k个的情况
其实就是个01背包,,
不过这题还有一个问题就是怎样输出方案
这里用的办法是:查找目标状态由哪个状态递推而来然后向后退(也是根据状态转移方程)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5010;
int n,m;
int a[maxn][maxn];//给i个分配j台机器的最大收益
int f[maxn][maxn];
void work()
{
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=j;k++)
f[i][j]=max(f[i][j],a[i][k]+f[i-1][j-k]);
cout<<f[n][m]<<endl;
}
void print_ans(int i,int j)
{
if(i==0) return;
for(int k=j;k>=0;k--)
{
if(f[i][j]==f[i-1][j-k]+a[i][k])
{
print_ans(i-1,j-k);
cout<<i<<" "<<k<<endl;
break;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
work();
print_ans(n,m);
return 0;
}