打砖块
【题目大意】
给定k发子弹,要求得到最大的得分。在打碎某些砖块后,可能有一发子弹的奖励。
【解法一】
不考虑奖励的子弹,那么本题为一道简单的动态规划:
设b[i][j]表示对着前i列的砖块打j发子弹,能达到的最大得分。
考虑对着第i列发多少发子弹,可以得到状态转移方程为:
b[i][j]=max(b[i-1][j-k]+s[i][k]), (0≤k,k≤ j,k≤n)
其中s[i][k]表示对着第i列打k.发子弹的得分。这个数组可以在O(nm)时间内预处理出来。
最终答案为b[m][k]。时间复杂度为Ol(mnk)。预计得分50。
【解法二】
解法一的缺陷在于没有考虑能否得到一发奖励的子弹。对于一个能打到的砖块,如果有奖励子弹,那么能打肯定打,因为打了以后,不仅有得分,而且子弹也没有减少。所以解法一中的b[i][j]的定义稍作修改,b[i][j]表示对着前i列的砖块打j发自己的子弹(不包括奖励的子弹),能达到的最大得分。
考虑对着第i列发多少发子弹,同样可以得到状态转移方程为:
b[i][j]=ma x(b[i-1][j-k]+s[i][k] (0≤k,k≤j,k≤n)
其中s[i][k]表示对着第i列打k发子弹的得分,如果在这个过程中有奖励子弹,那么奖励的子弹也对着这一列打。
这又产生了一个新的问题,对着第i列的砖打了k发子弹后,可能这一列现在处于最
下方的砖是有奖励子弹的,那么这一块砖的得分算不算在s[i][k]呢?
这需要分情况讨论:够最后一发子弹打的那一列不能算,而其余的都要算上。因为对
于别的列,可以借这最后一发的子弹先打砖块,然后用奖励的子弹归还。所以b数组要改
变两个:by[i][j]表示对着前i列的砖块打j发自己的子弹,且最后一发子弹不是对着前i列发,能达到的最大得分;by[i][j]表示对着前i列的砖块打j发自己的子弹,且最后一发子弹对着前i列发,能达到的最大得分。
递推的时候要讨论当前对着第i列的子弹是不是最后发的。
时间复杂度仍为O(mnk)。预计得分100。
【出题人的意图】
本题是这次模拟赛的第2题。因为基本上每年的NO I P都有一道动态规划的题目,所
以决定本题考动态规划。开始时想到了没有奖励子弹的模型,后来想加大一点难度,所以
就改成了奖励一发子弹的情形。
解法二中,如果没有分情况考虑,那么会失去一部分的分数。如果认为一定算在内,那
么失50分,如果认为一定不算在内,那么失40分。