#lydlx05x0E04. 花店橱窗

花店橱窗

题目描述

小 q 和他的老婆小 z 最近开了一家花店,他们准备把店里最好看的花都摆在橱窗里。

但是他们有很多花瓶,每个花瓶都具有各自的特点,因此,当各个花瓶中放入不同的花束时,会产生不同的美学效果。

为了使橱窗里的花摆放的最合适,他们得想个办法安排每种花的摆放位置。

可是因为小 q 和小 z 每天都太忙,没有时间设计橱窗里花的摆法,所以他们想让你帮他们求出花摆放的最大美观程度和每种花所放的位置。

每种花都有一个标识,假设杜鹃花的标识数为 1,秋海棠的标识数为 2,康乃馨的标识数为 3,所有的花束在放入花瓶时必须保持其标识数的顺序,即:

杜鹃花必须放在秋海棠左边的花瓶中,秋海棠必须放在康乃馨左边的花瓶中。

如果花瓶的数目大于花束的数目。则多余的花瓶必须空置,且每个花瓶中只能放一束花。

每种花放在不同的瓶子里会产生不同的美观程度,美观程度可能是正数也可能是负数。

为取得最大美观程度,你必须在保持花束顺序的前提下,使花束的摆放取得最大的美学值,并求出每种花应该摆放的花瓶的编号。

输入格式

第 1 行:两个整数 FFVV,表示共有 FF 种花,VV 个花瓶。

第 2 行到第 F+1F+1 行:每行有 VV 个数,表示花摆放在不同花瓶里的美观程度值 valuevalue。(美观程度和小于 2312^{31},美观程度有正有负)

输出格式

输出有两行:

第一行为输出最大美观程度和的值。

第二行有 FF 个数表示每朵花应该摆放的花瓶的编号。

若有多种方案,输出字典序较小的方案(美观程度不变的情况下,花尽量往前放)。

样例

3 5 
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20
53
2 4 5

样例解释

数据

  • F=3F = 3(3 种花)
  • V=5V = 5(5 个花瓶)

美观程度矩阵:

花 \ 花瓶 1 2 3 4 5
1 (杜鹃花) 7 23 -5 -24 16
2 (秋海棠) 5 21 -4 10 23
3 (康乃馨) -21 5 -20 20

要求

  • 花必须按编号顺序摆放(1 在 2 左边,2 在 3 左边)。
  • 每个花瓶最多放一束花。
  • 花瓶可以空置。
  • 求最大美观程度和,并输出每朵花应放的花瓶编号(字典序最小)。

最优解

摆放方案:

  • 花 1 放在花瓶 2 → 美观值 23
  • 花 2 放在花瓶 4 → 美观值 10
  • 花 3 放在花瓶 5 → 美观值 20

总和 = 23 + 10 + 20 = 53

其他方案比较

如果花 1 放在花瓶 1(7),花 2 放在花瓶 2(21),花 3 放在花瓶 5(20),总和 = 48 < 53。
如果花 1 放在花瓶 2(23),花 2 放在花瓶 3(-4),花 3 放在花瓶 5(20),总和 = 39 < 53。
等等。

字典序要求:在美观程度相同的情况下,花尽量往前放(即编号小的花尽量选择编号小的花瓶)。但本题最优解唯一。

数据范围

  • 1FV1001 \le F \le V \le 100
  • 美观程度值在 int 范围内(有正有负)

算法分析

这是一个动态规划问题,类似于“将 FF 个有序物品放入 VV 个位置,每个位置最多放一个,且物品顺序必须保持,求最大总价值”。

状态定义

dp[i][j]dp[i][j] 表示将前 ii 种花放入前 jj 个花瓶(且第 ii 种花恰好放在第 jj 个花瓶)的最大美观程度和。

转移方程

ii 种花放在第 jj 个花瓶时,前 i1i-1 种花必须放在前 j1j-1 个花瓶中,且第 i1i-1 种花放在某个位置 kk,其中 i1kj1i-1 \le k \le j-1

因此:

$$dp[i][j] = \max_{i-1 \le k \le j-1} \{ dp[i-1][k] \} + value[i][j]$$

其中 value[i][j]value[i][j] 表示第 ii 种花放在第 jj 个花瓶的美观值。

初始化

  • dp[1][j]=value[1][j]dp[1][j] = value[1][j],对 1jV1 \le j \le V
  • 其他 dp[i][j]=dp[i][j] = -\infty

优化

转移时需要求 dp[i1][k]dp[i-1][k] 在区间 [i1,j1][i-1, j-1] 的最大值,可以在遍历 jj 的过程中维护前缀最大值,将复杂度从 O(F×V2)O(F \times V^2) 降为 O(F×V)O(F \times V)

输出方案

为了输出字典序最小的方案,我们需要记录转移路径。定义 pre[i][j]pre[i][j] 表示状态 dp[i][j]dp[i][j] 是由 dp[i1][pre[i][j]]dp[i-1][pre[i][j]] 转移而来。

在求 dp[i][j]dp[i][j] 时,如果有多个 kk 都能得到相同最大值,选择最小的 kk(即字典序更小,因为花 i1i-1 的位置尽量靠前,那么花 ii 的位置也会相对靠前)。

最后从 dp[F][j]dp[F][j] 中找最大值(FjVF \le j \le V),然后逆推路径。

字典序处理

题目要求“花尽量往前放”,即对于相同的总美观值,我们希望花的摆放位置编号尽可能小。
在动态规划时,如果多个 kk 得到相同的 dp[i1][k]dp[i-1][k],我们选择最小的 kk,这样花 i1i-1 的位置更靠前,后续花的位置也更容易靠前。

在最后选择 dp[F][j]dp[F][j] 的最大值时,如果有多个 jj 得到相同的最大值,选择最小的 jj(即最后一朵花尽量靠前),然后逆推回去。

实现步骤

  1. 读入 F,VF, V 和美观值矩阵 value[F][V]value[F][V]
  2. 初始化 dpdp 数组为负无穷,dp[1][j]=value[1][j]dp[1][j] = value[1][j]
  3. 对于 i=2i = 2FF
    • 维护一个变量 maxValmaxValmaxIdxmaxIdx 表示 dp[i1][k]dp[i-1][k]kki1i-1j1j-1 的最大值及对应的最小 kk
    • 对于 j=ij = iVV(因为前 ii 朵花至少需要 ii 个花瓶):
      • 更新 maxValmaxValmaxIdxmaxIdx(考虑新的 k=j1k = j-1)。
      • dp[i][j]=maxVal+value[i][j]dp[i][j] = maxVal + value[i][j],记录 pre[i][j]=maxIdxpre[i][j] = maxIdx
  4. dp[F][j]dp[F][j]j=Fj = FVV)中找到最大值,如果有多个,选最小的 jj
  5. 逆推路径,得到每朵花的花瓶编号,然后正序输出。

复杂度

  • 时间复杂度:O(F×V)O(F \times V)
  • 空间复杂度:O(F×V)O(F \times V)