信息学奥赛一本通 1279:【例9.23】橱窗布置(flower) | 洛谷 P1854 花店橱窗布置
【题目链接】
ybt 1279:【例9.23】橱窗布置(flower)
洛谷 P1854 花店橱窗布置
吐槽:一本通中给的测试数据中,负号是全角负号!怪不得每次数据读不完程序就结束了。还是用洛谷的测试数据吧。
【题目考点】
1. 动态规划
【解题思路】
1. 状态定义
集合:摆花的方案
限制:选择前几束花,放在前几个瓶子中
属性:美学值
条件:最大
统计量:美学值
状态定义:dp[i][j]
:将前i束花放入前j个瓶子中,美学值最大的方案的美学值。
初始状态:前0束花放入j个花瓶中,美学值为0。所以dp[0][j] = 0
。
2. 状态转移方程
记将第i束花放入第j个瓶子得到的美学值为a[i][j]
。
集合:将前i束花放入前j个瓶子
本题分割集合的方法有两种,因此状态转移方程也有两种。
解法1:
分割集合:根据将第i束花放入第几个瓶子来分割集合
- 如果把第i束花放入第j个瓶子,那么接下来需要把前i-1束花放入前j-1个瓶子中获得最大美学值。
dp[i][j] = dp[i-1][j-1] + a[i][j]
- 如果把第i束花放入第j-1个瓶子,那么接下来需要把前i-1束花放入前j-2个瓶子中获得最大美学值。
dp[i][j] = dp[i-1][j-2] + a[i][j-1]
… - 如果把第i束花放入第i个瓶子,那么接下来需要把前i-1束花放入前i-1个瓶子中获得最大美学值。
dp[i][j] = dp[i-1][i-1] + a[i][i]
- 以上多种情况取最大值。
- 综上,k从i循环到j,
dp[i][j] = max(dp[i][j], dp[i-1][k-1] + a[i][k])
解法2:
分割集合:根据将第i束花是否放入第j瓶子来分割集合
- 如果把第i束花放入第j个瓶子,那么接下来需要把前i-1束花放入前j-1个瓶子中获得最大美学值。
dp[i][j] = dp[i-1][j-1] + a[i][j]
- 如果不把第i束花放入第j瓶子,那么接下来需要把前i束花放入前j-1个瓶子中获得最大美学值。
dp[i][j] = dp[i][j-1]
- 以上两种情况取最大值
3. 具体做法:
1. 瓶子编号j的循环范围
由于每束花都要放在某个花瓶中,前i束花放入前j个瓶子中,瓶子数量必须大于等于花的数量,所以 j ≥ i j \ge i j≥i。
一共有f束花v个瓶子,在前i束花放入前j个瓶子时,还剩下f-i束花,v-j个瓶子,剩下的瓶子的数量也一定要大于等于花的数量,因此 v − j ≥ f − i v-j \ge f-i v−j≥f−i,即 j ≤ v − f + i j \le v-f+i j≤v−f+i
所以j从i循环到v-f+i。
2. 记录方案
设数组b,b[i][j]
表示如果将前i束花放入前j个瓶子,第i束花所在的瓶子。
如果确定将花放入第k瓶子能获得最大美学值,可以更新dp[i][j]
,那么也同时更新b[i][j] = k
。
如果将前i束花放入前j个瓶子与放入前j-1个瓶子能获得的最大美学值一样,那么将前i束花放入前j个瓶子第i束花所在的瓶子,与将前i束花放入前j-1个瓶子第i束花所在的瓶子也是一样的,所以b[i][j] = b[i][j-1]
。
输出时通过递归的方法逆序输出,前i束花放入前j个瓶子,第i束花在b[i][j]
,那么先输出前i-1束花放在前b[i][j]-1
个瓶子中的情况,再输出b[i][j]
。
3. 复杂度
方法2的时间复杂度稍优于方法1。由于f与v最多为 100 100 100, O ( n 2 ) O(n^2) O(n2)或 O ( n 3 ) O(n^3) O(n3)的复杂度都能过。
空间复杂度上,方法1可以做滚动数组优化,不过没有必要,输入数据和b数组都是 O ( n 2 ) O(n^2) O(n2)复杂度的,滚动数组优化后并不能减少整体的空间复杂度。
【题解代码】
解法1:三重循环
#include<bits/stdc++.h>
using namespace std;
#define N 105
int f, v, a[N][N], dp[N][N];//dp[i][j]:前i个束花放在前j个花瓶中能得到的最大美学度
int b[N][N];//b[i][j]:前i个花束放入前j个瓶子,第i束花在哪个瓶子
void show(int i, int j)//输出前i个花束放入前j个瓶子各花束的位置
{if(i == 0)return;show(i-1, b[i][j]-1);cout << b[i][j] << ' ';
}
int main()
{cin >> f >> v;for(int i = 1; i <= f; ++i)for(int j = 1; j <= v; ++j)cin >> a[i][j];memset(dp, 0xc0, sizeof(dp));//初始化为负无穷for(int j = 0; j <= v; ++j)dp[0][j] = 0;for(int i = 1; i <= f; ++i)for(int j = i; j <= v-f+i; ++j)for(int k = i; k <= j; ++k){if(dp[i][j] < dp[i-1][k-1] + a[i][k]){dp[i][j] = dp[i-1][k-1] + a[i][k];b[i][j] = k; }}cout << dp[f][v] << endl;show(f, v);return 0;
}
解法2:二重循环
#include<bits/stdc++.h>
using namespace std;
#define N 105
int f, v, a[N][N], dp[N][N];//dp[i][j]:前i个束花放在前j个花瓶中能得到的最大美学度
int b[N][N];//b[i][j]:前i个花束放入前j个瓶子,第i束花在哪个瓶子
void show(int i, int j)//输出前i个花束放入前j个瓶子各花束的位置
{if(i == 0)return;show(i-1, b[i][j]-1);cout << b[i][j] << ' ';
}
int main()
{cin >> f >> v;for(int i = 1; i <= f; ++i)for(int j = 1; j <= v; ++j)cin >> a[i][j];memset(dp, 0xc0, sizeof(dp));//初始化为负无穷for(int j = 0; j <= v; ++j)dp[0][j] = 0;for(int i = 1; i <= f; ++i)for(int j = i; j <= v-f+i; ++j){if(dp[i][j-1] < dp[i-1][j-1]+a[i][j]){dp[i][j] = dp[i-1][j-1]+a[i][j];b[i][j] = j; }else{dp[i][j] = dp[i][j-1];b[i][j] = b[i][j-1];}}cout << dp[f][v] << endl;show(f, v);return 0;
}
信息学奥赛一本通 1279:【例9.23】橱窗布置(flower) | 洛谷 P1854 花店橱窗布置相关推荐
- 花店橱窗布置(洛谷P1854)(动态规划)
传送门 文章目录 解析 问题 代码 解析 一道很正常的动态规划 dp[i][j]表示到第j个花瓶放了第j朵花的dp最优值 注意:是严格使第i朵放在j瓶 找到最优解递归输出即可 问题 又是初始化的问题! ...
- 【例1】 0/1背包《信息学奥赛一本通》【解法一】 02
/* [例1] 0/1背包<信息学奥赛一本通>[解法一] 02 http://ybt.ssoier.cn:8088/problem_show.php?pid=1267 */ #includ ...
- 【例8】合唱队形(《信息学奥赛一本通第五版》)
/* [例8]合唱队形(<信息学奥赛一本通第五版>) http://ybt.ssoier.cn:8088/problem_show.php?pid=1264 [问题描述] N位同学站成一排 ...
- 信息学奥赛一本通 2021:【例4.6】最大公约数
[题目链接] ybt 2021:[例4.6]最大公约数 [题目考点] 1. while循环 2. 求最大公约数 辗转相减法 辗转相除法 [解题思路] 解法1:枚举 取较小数字,从该数字的值开始从大到小 ...
- 信息学奥赛一本通(2032:【例4.18】分解质因数)
2032:[例4.18]分解质因数 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 582 通过数: 376 [题目描述] 把一个合数分解成若干个质因数乘积 ...
- 信息学奥赛一本通——2062:【例1.3】电影票
2062:[例1.3]电影票 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 57341 通过数: 34230 [题目描述] 已知一位小朋友的电影票价是10 ...
- 信息学奥赛一本通 1278:【例9.22】复制书稿(book) | 洛谷 P1281 书的复制
[题目链接] ybt 1278:[例9.22]复制书稿(book) 洛谷 P1281 书的复制 [题目考点] 1. 动态规划:线性动规 [解题思路] 该题可以抽象为:将由m个数字构成的序列分成k个子段 ...
- 信息学奥赛一本通1267:【例9.11】01背包问题(二维dp与滚动数组优化)
[题目描述] 一个旅行者有一个最多能装 MM 公斤的背包,现在有 nn 件物品,它们的重量分别是W1,W2,...,WnW1,W2,...,Wn,它们的价值分别为C1,C2,...,CnC1,C2,. ...
- 信息学奥赛一本通C++语言-----2036:【例5.3】开关门
[题目描述] 宾馆里有n(2≤n≤1000)n(2≤n≤1000) 个房间,从1∼n1∼n 编了号.第一个服务员把所有的房间门都打开了,第二个服务员把所有编号是22 的倍数的房间"相反处理& ...
最新文章
- 私人定制---打造属于自己的linux小系统
- hyperledge环境安装
- 通用的异步处理类和进度通知类及其示例
- 单例模式:Instance
- 数据挖掘学习日志(part1)--熵值法
- 理解计算机网络的拓扑结构,认识计算机网络拓扑结构
- C#4.0新特性:可选参数,命名参数,Dynamic
- HDU 6043 Balala Power! 思维 + 码力
- Python数据分析师特训营84节
- java使用百度翻译接口实现前后端翻译功能
- excel字符串和单元格拼接_单元格引用问题(引用的单元格与字符串变量连接)...
- css选择器权重排序_css选择器的权重计算
- LensFlare Studio for Mac(镜头光晕特效工具)
- xtend怎么使用_Java替代Xtend又推出了另一个块摇摆更新
- 服务器和交换机物理连接_服务器与交换机连接及校园网搭建方案
- vue实现通讯录功能
- maya2018英文翻译_玛雅maya2018mac版如何改成英文?
- 细数2021年前端圈发生的30多件大事
- 跻身全球前十,金山云欲用AIoT再破局
- 浅析硬件“好声音”: 声学器件