SGU 104 Little Shop of Flowers 翻译 题解

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 < stdio.h >
#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 ;
}

转载于:https://www.cnblogs.com/yylogo/archive/2011/06/06/SGU-104.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值