• 实验7投资问题


    问题:

    设$m$元钱,$n$项投资,函数$f[i][x]$表示将$x$元投入第i项项目所产生的效益,$i=1,2,…,n$.问:如何分配这$m$元钱,使得投资的总效益最高?

    解析:

    背包问题。

    设$dp[i][j]$表示在前$i$个项目投入$j$元所产生的最大效益。

    转移方程为:

    $dp[i][j] = max( dp[i][j] , dp[i - 1][ j - k] + f[i][k] )$

    对于每个项目的投资,可以记录$x[i][j]$表示对于前$i$个项目总共投资$j$元时,对项目$i$的投资。

    则对每个项目的投资可以由最后一个倒推回来。

    $ans[i] = x[i][m] , m -= ans[i] $

    设计(核心代码):

     1 for (int i = 1; i <= n; ++i)
     2 {
     3     for (int j = 0; j <= m; ++j)
     4     {
     5         for (int k = 0; k <= j; ++k)
     6         {
     7             if (dp[i][j] < dp[i - 1][j - k] + f[i][k])
     8             {
     9                 dp[i][j] = dp[i - 1][j - k] + f[i][k];
    10                 x[i][j] = k;
    11             }
    12         }
    13     }
    14 }
    15 ans[n] = x[n][m];
    16 int tmp_m = m - ans[n];
    17 for (int i = n - 1; i >= 1; --i)
    18 {
    19     ans[i] = x[i][tmp_m];
    20     tmp_m -= ans[i];
    21 }

    分析:

    复杂度:$O(nm^2)$

    源码:

    https://github.com/Big-Kelly/Algorithm

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int inf = 2e9 + 7;
     5 const ll Inf = 1e18 + 7;
     6 const int maxn = 3e3 + 5;
     7 const int mod = 1e9 + 7;
     8 
     9 int dp[maxn][maxn];  //dp[i][j]表示前i件投j元的最大收益
    10 int f[maxn][maxn];   //f[i][j]表示第i件投资j元的最大收益
    11 int x[maxn][maxn];   //x[i][j]表示前i件投入j元时第i件的投资
    12 int ans[maxn];       //表示收益最大时每个的投资
    13 
    14 int main()
    15 {
    16     int n, m;
    17     scanf("%d %d", &n, &m);
    18     for (int i = 1; i <= n; ++i)
    19     {
    20         for (int j = 1; j <= m; ++j)
    21         {
    22             scanf("%d", &f[i][j]);
    23         }
    24     }
    25     for (int i = 1; i <= n; ++i)
    26     {
    27         for (int j = 0; j <= m; ++j)
    28         {
    29             for (int k = 0; k <= j; ++k)
    30             {
    31                 if (dp[i][j] < dp[i - 1][j - k] + f[i][k])
    32                 {
    33                     dp[i][j] = dp[i - 1][j - k] + f[i][k];
    34                     x[i][j] = k;
    35                 }
    36             }
    37         }
    38     }
    39     ans[n] = x[n][m];
    40     int tmp_m = m - ans[n];
    41     for (int i = n - 1; i >= 1; --i)
    42     {
    43         ans[i] = x[i][tmp_m];
    44         tmp_m -= ans[i];
    45     }
    46     printf("投资的最大收益是%d元
    ", dp[n][m]);
    47     for (int i = 1; i <= n; ++i)
    48     {
    49         printf("对第%d个项目的投资为%d元
    ", i, ans[i]);
    50     }
    51 }
    View Code
  • 相关阅读:
    【转载】关于C#中动态加载AppDomain的问题
    poj2239
    poj2231
    poj2229
    poj2234
    poj2236
    前 路
    只含一个单词的句子
    做人准则
    改变人生的32句励志名言
  • 原文地址:https://www.cnblogs.com/zhang-Kelly/p/12694137.html
Copyright © 2020-2023  润新知