SGU[104] Little shop of flowers
Description
描述
You want to arrange the window of your flower shop in a most pleasant way. You have F bunches of flowers, each being of a different kind, and at least as many vases ordered in a row. The vases are glued onto the shelf and are numbered consecutively 1 through V, where V is the number of vases, from left to right so that the vase 1 is the leftmost, and the vase V is the rightmost vase. The bunches are moveable and are uniquely identified by integers between 1 and F. These id-numbers have a significance: They determine the required order of appearance of the flower bunches in the row of vases so that the bunch i must be in a vase to the left of the vase containing bunch j whenever i < j.
你想要把按最舒适的方法安排你花店的窗口。你有F束花,每束都不一样,并且至少有F个花瓶排成一列。花瓶被粘在书架上,并且从左到右,从1到V连续的编号,其中V是花瓶总数。因此1号花瓶在最左边,V号花瓶在最右边。花束可以移动并且被标上1到F的不同的编号。这些id号码有一个作用:它们决定了花束在这一列中出现的次序。因此第i束花必须放在第j束花所在花瓶的左边,其中i < j。
Suppose, for example, you have bunch of azaleas (id-number=1), a bunch of begonias (id-number=2) and a bunch of carnations (id-number=3). Now, all the bunches must be put into the vases keeping their id-numbers in order. The bunch of azaleas must be in a vase to the left of begonias, and the bunch of begonias must be in a vase to the left of carnations. If there are more vases than bunches of flowers then the excess will be left empty. A vase can hold only one bunch of flowers.
假设这样的情况,你有一束杜鹃花(id = 1),一束秋海棠(id = 2)以及一束康乃馨(id = 3)。现在,所有的haunted都必须被放在花瓶里且保证它们的id顺序不变。杜鹃花必须放在秋海棠的左边,同时秋海棠必须放在康乃馨的左边。如果有多个花瓶可以放花,多余的花瓶被留空。一个花瓶只能放置一束花。
Each vase has a distinct characteristic (just like flowers do). Hence, putting a bunch of flowers in a vase results in a certain aesthetic value, expressed by an integer. The aesthetic values are presented in a table as shown below. Leaving a vase empty has an aesthetic value of 0.
每个花瓶有一个特定的标志(和花一样)。因此,把一束花放在花瓶里会得到一个魅力值,由一个整数表示。魅力值以一张表格显示如下。留空的花瓶的魅力值记为0。
V A S E S |
||||||
1 |
2 |
3 |
4 |
5 |
||
Bunches 花束 |
1 (azaleas) 杜鹃花 |
7 |
23 |
-5 |
-24 |
16 |
2 (begonias) 秋海棠 |
5 |
21 |
-4 |
10 |
23 |
|
3 (carnations) 康乃馨 |
-21 |
5 |
-4 |
-20 |
20 |
According to the table, azaleas, for example, would look great in vase 2, but they would look awful in vase 4.
由上面的表格所知,例如杜鹃花,放在2号花瓶里最好看,放在4号花瓶里最难看。
To achieve the most pleasant effect you have to maximize the sum of aesthetic values for the arrangement while keeping the required ordering of the flowers. If more than one arrangement has the maximal sum value, any one of them will be acceptable. You have to produce exactly one arrangement.、
为了达到一个最好的效果,你需要合理的安排花朵,以使得魅力值的和最大。如果不止一个安排能够获得最大的魅力值,任何一个安排都是可被接受的,你只需要输出其中一个。
1 ≤ F ≤ 100 where F is the number of the bunches of flowers. The bunches are numbered 1 through F.
1 <= F <= 100,其中F表示花束的个数,从1到F编号。
F ≤ V ≤ 100 where V is the number of vases.
F <= V <= 100,其中V是花瓶数。
-50 ≤ Aij ≤ 50 where Aij is the aesthetic value obtained by putting the flower bunch i into the vase j.
-50 <= Aij <= 50,其中Aij表示将第i束花放到第j个花瓶中获得的魅力值。
Input
输入
The first line contains two numbers: F, V.
第一行包含两个整数:F,V。
The following F lines: Each of these lines contains V integers, so that Aij is given as the j’th number on the (i+1)’st line of the input file.
接下来F行:每行包含V个整数,其中Aij为第i+1行的第j个数字。
Output
输出
The first line will contain the sum of aesthetic values for your arrangement.
第一行包含一个整数,表示你的安排的魅力值的和。
The second line must present the arrangement as a list of F numbers, so that the k’th number on this line identifies the vase in which the bunch k is put.
第二行为F个数字,表示一个安排,因此第k个数字表示第k束花放的位置。
Sample Input
样例输入
3 5
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20
Sample Output
样例输出
53
2 4 5
Analysis
分析
经典的动态规划题。我们令f[i][j]表示前i束花放到前j个花瓶中获得的最大的魅力值。
由于花束必须按编号递增安排,所以我们可以得到状态转移方程:
f[i][j] = max(f[i][j - 1], f[i - 1][j - 1] + pData[i][j])
即f[i][j]这个状态可以由f[i][j - 1](第i束花不放在第j个花瓶里)以及f[i - 1][j - 1](第i束花放在第j个花瓶里)转移过来。
这道题目还需要输出方案,我们需要记录转移过程。
我的方法是令一个结构体,保存它是由那个状态转移过来的,并且是否放置了花束。
输出方案的时候递归输出即可。
还有一个注意点,题目中的魅力值可能为负数。这为我们初始化f数组的时候带来了问题。
我选择的解决方案是把魅力值加上一个偏移量100,保证了魅力值为正数,然后把f数组全部置为0,输出的时候把魅力值减去100 * F即可。
Solution
解决方案
#include <iostream> #include <memory.h> using namespace std; const int MAX = 128; struct State { State(int _x = 0, int _y = 0, int _k = 0) { x = _x; y = _y; k = _k; } int x, y, k; }; int f[MAX][MAX], pData[MAX][MAX]; State pAns[MAX][MAX]; void Print(int x, int y); int main() { ios::sync_with_stdio(false); int F, V; while(cin >> F >> V) { memset(f, 0, sizeof(f)); for(int i = 1; i <= F; i++) { for(int j = 1; j <= V; j++) { cin >> pData[i][j]; pData[i][j] += 100; } } for(int i = 1; i <= F; i++) { for(int j = 1; j <= V; j++) { if(f[i][j - 1] < f[i - 1][j - 1] + pData[i][j]) { f[i][j] = f[i - 1][j - 1] + pData[i][j]; pAns[i][j] = State(i - 1, j - 1, 1); } else { f[i][j] = f[i][j - 1]; pAns[i][j] = State(i, j - 1, 0); } } } cout << f[F][V] - 100 * F << endl; Print(F, V); cout << endl; } return 0; } void Print(int x, int y) { if(x == 0 && y == 0) { return; } State tmp = pAns[x][y]; Print(tmp.x, tmp.y); if(tmp.k == 1) { cout << tmp.y + 1 << " "; } }
这道题目一开始WA了好几次,后来发现是没有发现魅力值为负数的时候,把f数组初始化为0会导致错误答案。