二解<花店橱窗布置>

花店橱窗布置题目见洛谷:https://www.luogu.org/problem/show?pid=1854
一.记忆化搜索
  这个问题第一眼看上去,它就是一个当初深搜求组合数的方案数的变形,m个花瓶插n朵花,而且这几朵花的顺序先后顺序不变,求和最大.是否有点像m个数取n个数组合,这n个数保证小的在前,大的在后,只不过是输出方案数而非和呢.看看数据规模100以内,想想,裸搜是一定会TLE的,但还是大胆地搜试试,果然AC1个点,9个点超时。
  想想这道题既然可以用动规解决,那在搜的过程中用适当的数组记下搜索产生的过程最优值,即记忆化搜索的方式对搜索剪枝也一定可以完成。于是采用了一个数组rem[101][101]来记录搜索过程中的最优值。如果之前对该第k朵花放至第t个花瓶及下方搜索完毕过,则直接返回rem[k][t],否则以搜索所有可能的情况,记录下最优值至rem[k][t]里。
  以样例数据为例,记忆化搜索树图如下,辅助理解:
  Markdown

#include<iostream>
#include<climits>
#include<iomanip>
using namespace std;
int n,m;
int flower[101][101];
int rem[101][101],can[101][101];
int dfs(int k,int t){    
    if(rem[k][t]!=0)  return rem[k][t] ;
    if(k==n){
        return rem[k][t] = flower[k][t];
    }
    int ansM=INT_MIN,temp=0;
    for(int j = t+1;j<= m-(n-k)+1; j++){
        temp = dfs(k+1,j) + flower[k][t];
        if(ansM < temp){
            ansM = temp;
            can[k][t] = j; 
        }        
    }
    rem[k][t] = ansM;
    return ansM;    
}
int main(){
    cin >> n >> m;
    for(int i = 1; i<= n; i++)
    {
        for(int j = 1; j<= m; j++)
            cin >> flower[i][j]; 
    }    
    cout << dfs(0,0) << endl;
    int x = INT_MIN,s=0;
    s = can[0][0];
    cout << s << " ";
    for(int i = 1; i< n; i++)
    {
        cout << can[i][s] <<" ";
        s = can[i][s];
    }
    cout << endl;
    return 0;
}

二.动态规划
Markdown
  如图,可以看到是一个有向无环图,题目要求的是这个图的最长路径,一个比较好的算法是动态规划.对于第i束花放至第j个花瓶时的可能产生的最美值,实际是前i-1束花放至第i-1 ~ j-1之间的最优值 + flower[i][j].因此可以以放入的花束个数为阶段,动态规划状态转移方程为:dp[i][j] = max(dp[i][j],dp[i-1][k] + flower[i][j]),并同时记录这个最大值由哪个k来更新的,方便后期输出方案.
详细程序如下:

#include<iostream>
#include<climits>
using namespace std;
int n,m;
int flower[101][101],dp[101][101];
int ans = INT_MIN,d=0;
int v[101],ansv[101];
int pat[101][101];
int main(){ 
    cin >> n >> m;
    for(int i = 1; i<= n; i++){
        for(int j = 1; j<= m; j++)
            cin >> flower[i][j]; 
    }
    for(int i = 1; i<= n; i++){
        dp[1][i] = flower[1][i];
    }
    for(int i =2; i<= n; i++)  //i代表花束
    {
        for(int j = i; j <= m-(n-i);j++){
            for(int k = i-1; k< j; k++){
                if(dp[i][j] < dp[i-1][k] + flower[i][j])                {
                    dp[i][j] = dp[i-1][k] + flower[i][j];
                    pat[i][j] = k;
                }
            }
        }
    } 
    int s;
    for(int i = n; i<=m; i++){
        if(ans<dp[n][i]){
            ans = dp[n][i];
            s = i;  
        }       
    }
    cout << ans << endl;
    for(int i=n; i>= 1; i--){
        v[i] = s;
        s = pat[i][s];
    }
    for(int i=1 ;i <= n; i++){
        cout << v[i] << " ";
    }
    return 0;
}

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>网上花店</title> <link rel="stylesheet" href="E:/HB文件/rdyud/styles.css"> <!-- 引入外部样式 --> </head> <body> <!-- 导航栏 --> <header> <nav> <ul class="nav-menu"> <li><a href=" ">首页</a ></li> <li><a href="#products">商品</a ></li> <li><a href="#about">关于我们</a ></li> <li><a href="#contact">联系我们</a ></li> </ul> </nav> </header> <!-- 中间内容板块 --> <main> <section id="home"> <h1>欢迎来到花店</h1> <object type="application/x-shockwave-fiash" data="animation.swf" width="600" height="400"> <param name="movie" value="animation.swf"> </object> </section> <section id="products"> <h2>热门商品</h2> <div class="product-list"> <div class="product-item"> < img src="D:\图片\c57cc668d03a9f9f4fef289310ea0d66.jpg" alt="玫瑰"> <p>玫瑰花束</p > </div> <div class="product-item"> < img src="D:\图片\428b2a66fbc88e9cf87d5673f7ebd65d.jpg" alt="百合"> <p>百合花束</p > </div> </div> </section> <section id="about"> <h2>关于我们</h2> <p>我们是一家专注花卉销售的网上商店,致力于提供优质服务.</p > </section> <section id="contact"> <h2>联系我们</h2> <p>电话:123456789</p > <p>邮箱:contact@flowrestore.com</p > </section> </main> <!-- 页脚 --> <footer> <p>© 2025 网上花店. 版权所有</p > </footer> </body> </html> 帮我制作轮播动画嵌入进去
最新发布
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值