POJ 1157 LITTLE SHOP OF FLOWERS (超级经典dp,两种解法)

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. 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.

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.
 

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.

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.

Input

  • The first line contains two numbers: F, V.
  • The following F lines: Each of these lines contains V integers, so that Aij is given as the jth number on the (i+1)st line of the input file.


  • 1 <= F <= 100 where F is the number of the bunches of flowers. The bunches are numbered 1 through F.
  • F <= V <= 100 where V is the number of vases.
  • -50 <= Aij <= 50 where Aij is the aesthetic value obtained by putting the flower bunch i into the vase j.

Output

The first line will contain the sum of aesthetic values for your arrangement.

Sample Input

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

Sample Output

53

题目意思:

每种花有一个编号,有几个花瓶,花瓶也是有编号的,每种花放在不同的花瓶的艺术价值不一样,
要你把这些花按某种策略放在这些花瓶里,得到艺术价值总值最大,
并且,编号小的花所在的花瓶的编号要比编号大的花所在花瓶的编号小。  

我的思想:

n=花种类,m=花瓶种类
输入数据的范围告诉你:n<=m
保证了插花方案的多样性
a[i][j]:表示第i朵花放第j个花瓶的艺术值
所以我们想象一下
1.前i种花放入前j个花瓶
2.前i种花放入前j-1个花瓶(要求编号小的花所在的花瓶的编号要比编号大的花所在花瓶的编号小。)

设dp[i][j]:表示前面i朵花放前面j个瓶子里面的艺术总值
1.对于前i种花放入前j个花瓶这种方案:就是前面的i-1种花放入前面j-1种花瓶里面,然后第i种花放入第j种花瓶里面
所以:dp[i][j]=dp[i-1][j-1]+a[i][j]

2.前i中花放入前j-1个花瓶
所以:dp[i][j-1]

取两种方案里面最大的那个
所以:
dp[i][j]=max(dp[i-1][j-1]+a[i][j],dp[i][j-1])


注意初始化的时候
dp[i][i]=dp[i-1][i-1]+a[i][i]
对角线初始化
因为第i朵花不能插编号i前面的花瓶
所以应该这样初始化!!!

code:
#include <iostream>
#include <cstdio>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<memory>
#include<queue>
#include<vector>
using namespace std;
#define max_v 105
#define INF 99999999
int dp[max_v][max_v];//前面i朵花放前面j个瓶子里面的艺术总值
int a[max_v][max_v];//第i朵花放第j个瓶子的艺术值
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
            }
            dp[i][i]=dp[i-1][i-1]+a[i][i];
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=m;j++)
            {
                dp[i][j]=max(dp[i-1][j-1]+a[i][j],dp[i][j-1]);
            }
        }
        printf("%d\n",dp[n][m]);
    }
    return 0;

}

思路二:

现在我们从另外一个角度思考

dp[i][j]:现在放第i种花到第j种瓶子里面得到的当前艺术总值

我们从第一种花开始放,那么我们需要的结果就是看把最后一朵花放入到哪个瓶子里面得到的艺术值中最大的哪个艺术值

dp[i][j]=max(dp[i-1][k])+a[i][j]

i-1<=k<j

所以说就是找一个最好的k,要使得当前的状态是最好的,那么我们就要找一个最好的上一个状态加上当前的值,那么这样当前的状态就是最好的

所以就是找一个合适的k

比如现在将第i种花插入到j种花瓶里面,在上一个状态中(插第i-1朵花)找一个合适的花瓶k使得上一个状态是最优的!

那就当前状态就是上面的最优状态加上当前i花插j瓶值的状态也是最优的

所以先开始初始化,我们知道每一种状态都是继承与上一种状态,插第一种花的时候,前面没有状态了,是继承不了的,算不出来,所以我们应该初始化给它赋值 dp[1][j]=a[1][j] j属于1到m

从第二种花开始算,在前面的状态中(插第一朵花)找个最优的加上i花插j瓶的值,那么当前状态就是最优的

注意数据范围:

算的时候i是2到n

j是i到m(要求编号小的花所在的花瓶的编号要比编号大的花所在花瓶的编号小)

k是i-1到j-1,不能取j,因为j是当前状态的值,你只能在前面找一个最好状态的k,不能找当前的嘛

注意理解状态转移方程:

dp[i][j]=max(dp[i-1][k])+a[i][j]

i-1<=k<j

code:

#include <iostream>
#include <cstdio>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<memory>
#include<queue>
#include<vector>
using namespace std;
#define max_v 105
#define INF 99999999
int dp[max_v][max_v];//现在放第i种花到第j种花瓶的艺术值
int a[max_v][max_v];//第i朵花放第j个瓶子的艺术值
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        for(int j=1;j<=m;j++)//初始化
            dp[1][j]=a[1][j];//第1种花放第j种花瓶中的艺术值
        for(int i=2;i<=n;i++)//从第二种花开始放
        {
            for(int j=i;j<=m;j++)//第i种花放的花瓶编号不能小于i,所以j属于i到m
            {
                int x=-INF;
                for(int k=i-1;k<j;k++)//找k
                {
                    x=max(x,dp[i-1][k]);
                }
                dp[i][j]=x+a[i][j];
            }
        }
        int ans=-INF;
       for(int j=n;j<=m;j++)//找max
       {
           ans=max(ans,dp[n][j]);
       }
       printf("%d\n",ans);
    }
    return 0;

}



猜你喜欢

转载自www.cnblogs.com/yinbiao/p/9443756.html
今日推荐