題面
【題目描述】
總公司擁有高設備臺,準備分給下屬的個分公司。各分公司獲得這些設備,可以爲國家提供一定的盈利。問:如何分配這臺設備才能使國家得到的盈利最大?求出最大盈利值。其中。分配原則:每個公司有權獲得任意數目的設備,但總檯數不超過設備數。
【輸入】
第行有兩個數,第個數是分公司數,第個數是總設備臺數。接下來是的矩陣,表明了第個公司分配臺機器的盈利。
【輸出】
第行輸出最大盈利值,接下來行,每行個數,即分公司編號和該公司獲得設備臺數。
【樣例輸入】
3 3
30 40 50
20 30 50
20 25 30
【樣例輸出】
70
1 1
2 1
3 1
算法分析
。
狀態:
——前個公司分臺設備的最大盈利。
狀態轉移方程:
如果前個公司已經分配完了,考慮第個公司分配的機器數量,設分得臺,可能爲~,那麼前個公司只能分配臺。
設表示第個公司分配臺設備的盈利。
因此,只需要考慮第個公司分配了多少臺機器:
{ },
邊界:
,個公司分配臺設備盈利爲.
,個公司分配臺設備盈利爲。
輸出方案
最後的答案爲,即個公司分臺設備的最優解。
通過狀態轉移方程可以知道,是由得到的,即前個公司分臺設備,第個公司分配臺設備。數組是已知的,數組也是已知的,而是未知的,因此,可以枚舉,檢驗在何時滿足,則找到了第個公司分配到的設備數。
同理,繼續找,檢驗第個公司分配的設備數…
採用遞歸來實現。
參考程序
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[200][200],dp[200][200],num[200],mx,s[200],ans=0;
void print(int i,int j) //遞歸尋找答案,前i個公司分j臺
{
if(ans) return; //找到答案不再找了
if(i==0)
{
int tmp=0;
for(int k=1;k<=n;k++)
tmp+=s[k];
if(tmp==m) //m臺設備全部分完
{
for(int k=1;k<=n;k++)
cout<<k<<' '<<s[k]<<endl;
ans=1;
}
return;
}
for(int k=0;k<=j;k++) //前i-1個公司分j-k臺,第i個公司分k臺
{
if(dp[i][j]==dp[i-1][j-k]+a[i][k])
{
s[i]=k; //記錄
print(i-1,j-k);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
mx=0;
for(int k=0;k<=j;k++) //考慮第i個公司分配了k臺設備
{
if(dp[i-1][j-k]+a[i][k]>mx) //取最優解
mx=(dp[i-1][j-k]+a[i][k]);
}
dp[i][j]=mx;
}
}
cout<<dp[n][m]<<endl;
print(n,m);
return 0;
}