花店橱窗

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
小q和他的老婆小z最近开了一家花店,他们准备把店里最好看的花都摆在橱窗里。

但是他们有很多花瓶,每个花瓶都具有各自的特点,因此,当各个花瓶中放入不同的花束时,会产生不同的美学效果。

为了使橱窗里的花摆放的最合适,他们得想个办法安排每种花的摆放位置。

可是因为小q和小z每天都太忙,没有时间设计橱窗里花的摆法,所以他们想让你帮他们求出花摆放的最大美观程度和每种花所放的位置。

每种花都有一个标识,假设杜鹃花的标识数为1,秋海棠的标识数为2,康乃馨的标识数为3,所有的花束在放入花瓶时必须保持其标识数的顺序,即:

杜鹃花必须放在秋海棠左边的花瓶中,秋海棠必须放在康乃馨左边的花瓶中。

如果花瓶的数目大于花束的数目。则多余的花瓶必须空置,且每个花瓶中只能放一束花。

每种花放在不同的瓶子里会产生不同的美观程度,美观程度可能是正数也可能是负数。

上述例子中,花瓶与花束的不同搭配所具有的美观程度,如下表所示:

花 瓶
、、、、、 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和V,表示共有F种花,V个花瓶。
第2行到第F+1行:每行有V个数,表示花摆放在不同花瓶里的美观程度值value。(美观程度和小于2^31 ,美观程度有正有负)

输出描述:
输出有两行:第一行为输出最大美观程度和的值,第二行有F个数表示每朵花应该摆放的花瓶的编号。
若有多种方案,输出字典序较小的方案(美观程度不变的情况下,花尽量往前放)。

思路 :核心:dp
此题最大的干扰处就是,每种花之间有放置顺序,限制了选择。假如现在正在抉择第i种花,需要确定前i-1种花是否选了,1~i-1的选择是第i种花选的必要条件,不确定的状态增加了思考的难度。
不妨将所有状态确定,枚举所有状态(感觉就是暴力),
f[i][j]表示第i种花必须放入第j个花瓶
则有dp方程f[i][j]=f[i-1][k]+w[i],
其中w[i][j]为第i种花在第j个花瓶的美观度,f[i-1][k]=max_element(f[i-1],f[i-1]+j-1),k属于[i,j-1]

解释一下,f[i][j]为前i-1种花放在前j-1个花瓶的最大美观值,而前j-1种花的放置需要维护一下美观最大值。
最后注意要按字典序输出,倒序逐行扫一遍就行。
(维护最大值我又用了一个循环,自己写的算法复杂度n^3@-@,如有更简单的算法,欢迎评论区留言~

//花店橱柜
//dp
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

ll mp[110][110]; //存输入数据
ll f[110][110]; //f[i][j]表示必选第1 ~ i种花放在前j个花瓶的方法
ll res[110]; // 每种花所在的花瓶
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    memset(f,-0x3f,sizeof(f));//状态初始化,一开始什么都没选

    int n,m;
    cin>> n>> m;
    for(int i=1;i<=n; i++)
        for(int j=1;j<=m;j++)   cin>>mp[i][j];


    for(int i=1;i<=m;i++)   f[1][i]=mp[1][i];//第一种花必选的话,美观值最大值就是自己

    for(int i=2;i<=n;i++)
        for(int j=i;j<=m;j++)
            for(int k=0;k<j;k++)
                f[i][j]=max(f[i-1][k]+mp[i][j],f[i][j]); // i必选的花,最大值是前i-1种花放在前j-1花瓶的最大美观值加上当前花的美观值

    ll ans=-0x3f3f3f3f;
//    for(int i=1;i<=m;i++)
//    ans=max(ans,f[n][i]);
//    cout<<ans<<endl;

    res[0]=m+1;
    int k=1;
    for(int i=n;i>= 1;i--)
    {
    
    
        ll temp=-0x3f3f3f3f3f3f3f3f;
      for(int j=res[k-1]-1;j>=1;j--)
      {
    
    
          if(f[i][j]>=temp)
          {
    
    
              temp=f[i][j];
              res[k]=j;
          }
      }
      k++;
        if(i==n)    cout<<temp<<endl;
    }

    for(int i=n;i>=1;i--)
        cout<<res[i]<<" ";
}

猜你喜欢

转载自blog.csdn.net/m0_53688600/article/details/113747201