采药(动态规划背包问题总结)

做了NOIP的题,是动态规划背包问题的典例。

采药

输入格式:

第一行有2个整数T(1T1000)和M(1M100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。

接下来的M行每行包括两个在1100之间(包括1100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出格式:

 1个整数,表示在规定的时间内可以采到的草药的最大总价值。

状态转移方程:

vis[i][j]=vis[i-1][j-xt[i]]+xw[i],当j>=xt[i];
vis[i][j]=vis[i-1][j],当j<xt[i];

其中vis[i][j]表示采摘前i个药时最大花费j时所能得到的最大价值,xw[i]是第i个药的价值,xt[i]是第i个药的费时。

代码如下:

for(int i=1;i<=m;i++)
    for (int j = 1;j <= t;j++)
    {
        if (j >= xt[i])
            vis[i][j] = max(vis[i - 1][j - xt[i]] + xw[i], vis[i - 1][j]);
        else
            vis[i][j] = vis[i - 1][j];
    }

 我们可以发现,vis数组每次i递进1时只用到上一层的i-1,所以可以用滚动数组替换,因为大的j(vis[i][j])在计算时要用到小的j(vis[i-1][j-?]),故要从t向下开始替换,以免替换之前的vis[i-1][?]被换成了vis[i][?]。状态转移方程如下:

vis[j]=vis[j-xt[i]]+xw[i],当j>=xt[i];
vis[j]=vis[j],当j<xt[i];

代码如下:

for(int i=1;i<=m;i++)
    for (int j = t;j >= 1;j--)
    {
        if (j >= xt[i])
            vis[j] = max(vis[j - xt[i]] + xw[i], vis[j]);
        else
            vis[j] = vis[j];
    }

猜你喜欢

转载自www.cnblogs.com/chendie/p/10454179.html