104. Little shop of flowers
每个测试点的时间: 0.5s
内存限制: 4096KB
问题:
你想将花店的窗户装饰到最令人舒适。你又F束花,每束花都各不相同,并且个数不少于排成一排的花瓶。花瓶被粘在架子上,并且被连续地从1编号到V,那么V就是花瓶的个数。从左到右1是最左边的花瓶,V是最右边的花瓶。花朵都是可移动的,并且都被表示成1到F。这些编号是有意义的:他们决定花和被安置在一排的花瓶的出现顺序,若i<j,则i花朵必须出现在j花朵的左边。一束杜鹃花(编号是1) 一束秋海棠(编号是2)和 一束康乃馨(编号是3)。现在所有的花朵必须放在花瓶中并保持他们编号上的顺序,杜鹃花放在必须在秋海棠的左边的花瓶中,并且秋海棠必须放在康乃馨的左边的花瓶中。如果花瓶数目比花要多的话,那就存在空花瓶。每个花瓶只能装一束花。
每个花瓶都有不同的特性(正如花朵一样) 。每束花朵放在一个花瓶中都会产生一个确定的审美值,用一个整数来表示。审美值被如下的表格给出。一个空花瓶产生的审美值为0。
花瓶 | ||||||
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 ≤ 100,代表花朵的数目。
- F ≤ V ≤ 100 ,代表花瓶的数目。
- -50 £ Aij £ 50 ,代表将花i插入j花瓶产生的审美值。
输入:
- 第一行包含整数F,V
- 接下来F行,每行包含N个整数,那么Aij就是第(i+2)行的第j个数字。
输出:
- 第一行是能产生的最大审美值。
- 第二行输出花的安排,包含F个数字,第k个数字代表第k朵花放在哪个花瓶中。
样例:
输入
3 5
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20
输出
53
2 4 5
================================华丽的分割线 ================================
天啊,翻译这题目累死我了,估计错别字还有不少,各位网友包含包含把,明天再写,今天只翻译算了。 2011年6月8日 21时26分51秒
好吧,经典的动态规划:f[i][j]=max{f[i][j-1],f[i-1][j-1]+num[i][j]},但是因为有负数,所以到底提交了多少次我也没有去统计,总之,提交了很多次,一直没解决负数问题,看到了网上的几个人的题解:
http://www.cppblog.com/master0503/articles/65840.html,说实话没看懂他代码里dp[i][i-1]=-32767;是干吗,但是它很有效的解决了负数问题,但是我一直没琢磨透原理,等下还看看,看能够看懂不,可能包含数学底蕴,又也许会是数据的漏洞,不知道,呵呵。
再有特色的就是这个 http://sqybi.72pines.com/posts/62,好独特的写法,有点难懂,毕竟我是C派,不是P派,没仔细琢磨,别的就不说了,说说我的思路。
我处理负数的方法就是在输入的时候每个数据加上50,直接处理掉负数,然后在输出结果的时候减去50*F就可以了,咋样?觉得不错的请鼓掌,谢谢。
#include < stdlib.h >
#define INF 0xFFFFF
int ans[ 101 ][ 101 ];
int num[ 101 ][ 101 ];
int from[ 101 ][ 101 ];
#define max(a, b) ((a)>(b)?(a):(b))
void output( int k, int l)
{
if (k == 1 ){
printf( " %d " , from[k][l]);
return ;
}
output(k - 1 , from[k][l] - 1 );
printf( " %d " , from[k][l]);
return ;
}
int main( int argc, char ** argv)
{
int f, v;
int i, j;
scanf( " %d%d " , & f, & v);
for (i = 1 ; i <= f; i ++ ){
for (j = 1 ; j <= v; j ++ ){
scanf( " %d " , & num[i][j]);
num[i][j] += 50 ;
}
}
for (i = 1 ; i <= f; i ++ ){
for (j = 1 ; j <= v - f + i; j ++ ){
if (ans[i][j - 1 ] < ans[i - 1 ][j - 1 ] + num[i][j]){
ans[i][j] = ans[i - 1 ][j - 1 ] + num[i][j];
from[i][j] = j;
} else {
from[i][j] = from[i][j - 1 ];
ans[i][j] = ans[i][j - 1 ];
}
}
}
printf( " %d\n " , ans[f][v] - 50 * f);
output(f, v);
printf( " \n " );
return 0 ;
}