题解 | #花店橱窗#

花店橱窗

https://ac.nowcoder.com/acm/problem/51216

  • 题目考点:二维线性DP (初学者可以参考代码对样例模拟状态转移的过程,有助于今后理解状态转移)

  • 题目大意:n种花m个花瓶,花瓶顺序以及插入花的顺序固定,每种花在每个花瓶中美观度不同(有负数),问讲n种花插在哪n个花瓶里美观度最大。

  • 题目分析:对于第i种花,它能获得的最大美观度为:在合法区间内,上一种花所在位置后面的花瓶中的最大美观度的位置(其中合法区间是指从上一种花(上一种花用k维护)放的位置开始,到使得i后面的话有花瓶可以放的区间,比如根据题目样例,对于第2种花来说,它最后能放的位置为4,后面至少留1个花瓶的位置)。
    因此转移方程:dp [ i ][ j ] = max (dp [ i ][ j ], dp [ i-1 ][ k ] + v [ i ][ j ]);
    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 105, INF = 0x3f3f3f3f;
    int dp[N][N], v[N][N], id[N];
    int n, m;
    int main()
    {
      scanf("%d%d", &n, &m);
    
      for(int i = 1; i <= n; i++)
      for(int j = 1; j <= m; j++)    //dp数组初始化极小值
          scanf("%d", &v[i][j]) , dp[i][j] = -INF;
    
      for(int i = 1; i <= n; i++)
      for(int j = i; j <= m - (n-i); j++) //第i种花的合法区间(合法区间的定义写在上面了)
      for(int k = i-1; k < j; k++)        //k维护上一层的摆放情况
          dp[i][j] = max(dp[i][j], dp[i-1][k] + v[i][j]);
    
      //寻找最大美观度
      int ans = -INF;
      for(int i = 1; i <= m; i++)
          ans = max(ans, dp[n][i]);
      printf("%d\n", ans);
    
      //寻找位置  
      int pos = n;
      for(int i = n; i ; i--)  //倒推寻找位置
      for(int j = 1; j <= m; j++)  //对于每一种花,遍历所在层寻找
          if(dp[i][j] == ans) //ans对应dp维护的值,证明找到了位置
          {
              id[pos--] = j;   
              ans -= v[i][j];
              break;   //该层位置找到后记得直接跳到再上一层寻找上一层的位置
          }
      for(int i = 1; i <= n; i++)  //输出n种花的位置
          printf("%d ", id[i]);
      return 0;
    }
题解专栏 文章被收录于专栏

希望不断进步

全部评论
请教一下大佬,k为什么要从i-1开始枚举呢
点赞 回复 分享
发布于 2022-01-18 16:59
这样能确保字典序最小吗
点赞 回复 分享
发布于 2022-03-05 09:19
为第三个花选择花瓶时,怎么确保维护2和3的时候,不会越过已经选好的1呢?
点赞 回复 分享
发布于 2022-07-05 09:27
确实,模拟一下对我的理解很有帮助,谢谢
点赞 回复 分享
发布于 2023-10-06 22:01 湖南

相关推荐

如题如果提出了一个薪资,A不成功,会有可能被取消offer吗
爱打瞌睡的柯基:最想去你们公司 但是别家开的高一些,希望能申请高一点 不管结果如何都谢谢你
点赞 评论 收藏
分享
10-09 19:35
门头沟学院 Java
洛必不可达:java的竞争激烈程度是其他任何岗位的10到20倍
点赞 评论 收藏
分享
牛客771574427号:恭喜你,华杰
点赞 评论 收藏
分享
评论
14
收藏
分享
牛客网
牛客企业服务