题目:http://www.nocow.cn/index.php/Translate:USACO/inflate
这道题目类似于算法与数据结构当中的01背包问题,只是这里的物品有数量的问题。但是还是可以用动态规划解决问题。
我们假设f[type][minute]表示对前面type种题目在minute分钟下最大的得分情况。用struct Problem{ int point; int minute;}结构体数组表示题目类型和分数。则
当type>1时,f[type][minute] = max(k * problem[type-1].point + f[type-1][minute - k * problem[type-1].minute]) ;(k属于0到minute / problem[type].minute之间)
当type=1时,f[type][minute] = minute / problem[type].minute * problem[type].point;
抽象出动态规模模型以后,代码就很容易实现了,代码如下:
然而遗憾的是,为了便于更快的得出答案,我们使用了一个二维的数组进行数据的存储,但是发现这个二维数组的利用率并不是很高,而且很快就超过了USACO的空间要求了。
在01背包问题中有一个空间优化的方法,我们可以试一试,重新建立模型。这一块我虽然能够理解,但是却讲不太清楚。可能会存在很多歧义,希望大家自己批判性的看,自己看代码,或者详细复习一下01背包问题的空间优化方法,斟酌其中的含义。
我们声明一个数组,f[minute],把每个单元想象成可以重复利用的小房间,房间的容量就是minute,如f[100]表示容量为100的小房间,他的值表示在房间下最大分数,因此初始值为0,那么对于一个m2 = m1 + problem[i].minute的空间,那么他的最大分数可以是 利用problem[i].minute装问题i,然后将m1空间充分利用的最大分数f[m1],或者不利用problem[i].minute的时间解决问题i,而是用这些时间解决前面i-1个问题的最大值,也就是上一次递归保存的f[m2]。因此递推的关键是每次迭代问题,空间都要从小开始往上递推。
因此,对于每次循环,f[minute] = max(f[minute] , f[minute - problem[i].minute] + problem[i].point) 。
觉得还是没讲清楚。直接上代码吧。