花店橱窗 题面 输入格式 输出格式 题解

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

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

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

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

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

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

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

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

上述例子中,花瓶与花束的不同搭配所具有的美观程度,如下表所示:

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

根据上表,杜鹃花放在花瓶2中,会显得非常好看;但若放在花瓶4中则显得十分难看。

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

输入格式

第1行:两个整数F和V,表示共有F种花,V个花瓶。

第2行到第F+1行:每行有V个数,表示花摆放在不同花瓶里的美观程度值value。(美观程度和小于231,美观程度有正有负)

输出格式

输出有两行:第一行为输出最大美观程度和的值,第二行有F个数表示每朵花应该摆放的花瓶的编号。

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

数据范围

1≤F≤V≤100,

输入样例:

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

输出样例:

53
2 4 5

题解

f[i][j] 表示到第i个花盆已经放了前j种花的最大值

记得初始化 -inf

转移方程

if (j == 0) f[i][j] = f[i][j - 1]

else f[i][j] = max(f[i - 1][j], f[i - 1][j - 1] + a[j][i]);

是可以空间优化的,但是! 我们要求放的顺序,所以不能优化

要输出字典序,那就倒叙找到 f[i - 1][j] != f[i][j] 则第j种花就放在 第i个花盆 O(n)复杂度

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, m, a[101][101], ans[101], f[101][101];

int main()
{
    cin >> m >> n;
    for (int i = 1; i <= m; ++i)
        for (int j = 1; j <= n; ++j) cin >> a[i][j];

    memset(f, 0xcf, sizeof f); f[0][0] = 0;

    for (int i = 1; i <= n; ++i)
        for (int j = 0; j <= min(i, m); ++j)
            if (j == 0) f[i][0] = f[i - 1][0]; 
            else f[i][j] = max(f[i - 1][j], f[i - 1][j - 1] + a[j][i]);

    cout << f[n][m] << '
';

    for (int i = n, j = m; j; ans[j--] = i--)
        while (f[i - 1][j] == f[i][j]) --i;

    for (int i = 1; i <= m; ++i) cout << ans[i] << ' ';
    return 0;
}