洛谷【P1854】花店橱窗布置

https://www.luogu.org/problemnew/show/P1854

题目描述

  某花店现有编号由 1 到 F 的 F 束花, 每一束花的品种都不一样. 编号由 1 到 V 的 V 个花瓶被按顺序摆成一行, 花瓶的数量至少和花的数量相同. 现在要把所有花放到花瓶中, 规定每个花瓶最多只能放一束花, 且 ∀ i < j, 第 i 束花必须放在第 j 束花的左侧.

  每个花瓶的形状和颜色不同, 因此放入不同的花会产生不同的美学效果. 空花瓶的美学值为 0. 请你给出一种方案, 使得总美学值最大.

输入输出格式

输入格式:

  第一行有两个整数 F 和 V, 分别为花束数和花瓶数 ( 1 ≤ F ≤ V ≤ 100 ).

  第二行到第 F + 1 行, 每行有 V 个整数. 第 i 行的第 j 个整数代表花束 i 放到花瓶 j 中的美学值.

输出格式:

  第一行输出一个整数,为最大美学值.

  第二行输出 F 个整数, 表示每束花放入的花瓶的编号.

输入输出样例

输入样例:

3 5

7 23 -5 -24 16

5 21 -4 10 23

-21 5 -4 -20 20

输出样例:

53

2 4 5

实现

  • 状态转移方程

  设 f[i][j] 为将编号 1 到 i 的花束放入编号 1 到 j 的花瓶中时最大的美学值, a[i][j]为将第 i 束花放入第 j 个花瓶所能产生的美学值, 有 f[i][j] = max(f[i - 1][j - 1] + a[i][j], f[i][j - 1]).

  • 滚动数组

  可以省去表示花束的一维, 用 f[i] 表示在前 i 个花瓶中放入当前数量花束的最大美学值.

  例如, 对于样例, 可以按如下方法计算:

  初始状态:

i 0 1 2 3 4 5
f[i] 0 0 0 0 0 0

  考虑第一束花后:

i 0 1 2 3 4 5
f[i] 0 7 23 -5 -24 16

  ∵ 此时 f[i] 表示在前 i 个花瓶中放入第一束花的最大美学值.

  ∴ ∀ i > j, f[i] ≥ f[j], f 数组应修改为:

i 0 1 2 3 4 5
f[i] 0 7 23 23 23 23

  以此类推, 考虑第二束花:

i 0 1 2 3 4 5
f[i] 0 0 28 19 33 46
i 0 1 2 3 4 5
f[i] 0 0 28 28 33 46

  考虑第三束花:

i 0 1 2 3 4 5
f[i] 0 0 0 24 8 53
i 0 1 2 3 4 5
f[i] 0 0 0 24 24 53

  由此得到答案 53. 显然, 题目所要求的摆放方案可以在刷表的同时记录下来.

实现

 1 #include <iostream>
 2 #include <cstdio>
 3 #define IsDigit(x) ((x) >= '0' && (x) <= '9')
 4 using namespace std;
 5 
 6 int f, v;
 7 int in[101][101], dp[101], plan[101][101][2], s[101];
 8 
 9 
10 int Read(void)
11 {
12     int c, ret(0), sign(false);
13     
14     c = getchar();
15     while (!IsDigit(c) && c != '-')
16         c = getchar();
17     c == '-' && (sign = true, c = getchar());
18     do
19         ret = ret * 10 + c - '0';
20     while ((c = getchar()) && IsDigit(c));
21     return sign ? -ret : ret;
22 }
23 
24 
25 int main()
26 {
27     int pos(0), nxt;
28     
29     f = Read();
30     v = Read();
31     for (int i = 1; i <= f; ++i)
32         for (int j = 1; j <= v; ++j)
33             in[i][j] = Read();
34     for (int i = 1; i <= f; ++i) {
35         for (int j = v - f + i; j >= i; --j) {
36             dp[j] = dp[j - 1] + in[i][j];
37             plan[i][j][0] = plan[i - 1][j - 1][1];
38             plan[i][j][1] = j;
39         }
40         for (int j = i + 1; j <= v - f + i; ++j)
41             dp[j - 1] > dp[j] &&
42              (dp[j] = dp[j - 1], plan[i][j][0] = plan[i][j - 1][0], plan[i][j][1] = plan[i][j - 1][1]);
43     }
44     nxt = v;
45     for (int i = f; i; --i) {
46         s[pos++] = plan[i][nxt][1];
47         nxt = plan[i][nxt][0];
48     }
49     printf("%d\n", dp[v]);
50     for (int i = pos - 1; i >= 0; --i)
51         printf("%d ", s[i]);
52     printf("\n");
53     return 0;
54 }

猜你喜欢

转载自www.cnblogs.com/justlikeoldtimes/p/10272613.html
今日推荐