WOJ 1023 Division题解
题目
参考
把一串包含n个数字的序列,分成若干个cluster,不改变数字在原来序列中的顺序(即相当于在原序列中插入隔板来分割),使得每个cluster满足如下要求:
- 至少包含p个元素
- 顺序为原list中的顺序
- 所有cluster的均方误差之和最小
均方误差的计算方法:
double squareDiviation(const vector<int>& s) {double sum = 0, res = 0;for_each(s.begin(), s.end(), [&sum](int val) { sum += val; });sum /= s.size();for_each(s.begin(), s.end(), [&res, sum](int val) { res += pow(val - sum, 2); });return res;
}
使用动态规划的准备工作:
- 计算所有可能的cluster的累加和
- 计算每个可能的cluster的均方误差
排列组合的思想,n个数字的序列,可以分为 n(n+1)/2 种不同的cluster,用矩阵保存相应的累加和,例如:clusterSum[i][j]
表示,第i个数一直加到j个数的累加和;clusterSquareDiv[i][j]
表示,第i个数到第j个数这个cluster的均方误差。
定义状态转移方程
dp是一个大小为(n+1)的一维数组,dp[i]
表示到第i个数(不包括i)为止,左边的cluster最小的均方误差和。
相当于我们已经知道了对于 j个数字的序列(以及小于j个数字的序列)的最优解,再增加一个数字后,如何划分cluster来达到最优解。
方法(类似滑动窗口):固定新cluster的右边界为这个新增的数字,移动cluster的左边界来查找能使得 (新cluster的均方误差) + (他左边的所有cluster的均方误差之和)最小 的一个界限。
初始条件
- dp[0] = 0
- dp[k] = MAX_VALUE, (k > 0 && k <= n)
转移方程
dp[j] = min({dp[k] + clusterSquareDiv[k][j-1] | 0 <= k < j - p })
代码实现
#include<iostream>
#include<vector>
#include <cmath>
#include <cstdio>
#include <algorithm>using namespace std;/*** 每一个小set要同时满足三个条件:* 1、至少包含p个元素* 2、包含的数要在原list中连续* 3、方差要尽量小* @return*/
int main() {int T;cin >> T;for (int i = 0; i < T; ++i) {int n, p;cin >> n >> p; // 每个小集合中至少p个元素vector<int> arr(n);vector<vector<int>> clusterSum(n , vector<int>(n));vector<vector<double>> clusterSquareDiv(n , vector<double>(n));for (auto& a : arr) {cin >> a;}// 计算每个小区间的和for (int j = 0; j < n; ++j) {for (int k = j; k < n; ++k) {if (j == k) {clusterSum[j][k] = arr[k];} else {clusterSum[j][k] = clusterSum[j][k - 1] + arr[k];}}}for (int j = 0; j < n; ++j) {for (int k = j + p - 1; k < n; ++k) {double tempBlockSum = (double)clusterSum[j][k] / (k - j + 1);for (int l = j; l <= k; ++l) {// 计算每个小区间的均方误差clusterSquareDiv[j][k] += pow(arr[l] - tempBlockSum, 2);}}}vector<double> dp(n+1, 1e15); // 注意!这个数要选择的足够大dp[0] = 0; // dp[i]表示到第i个数(不包括i)为止,左边的cluster最小的均方误差和for (int j = p; j <= n; ++j) { // cluster右边界for (int k = j - p; k >= 0; k--) {dp[j] = min(dp[j], dp[k] + clusterSquareDiv[k][j - 1]);}}if (i != 0) {cout << endl;}cout << "Case " << i+1 << ":\n";printf("%.2f\n", dp[n]);}return 0;
}
WOJ 1023 Division题解相关推荐
- [bzoj1023][SHOI2008]cactus仙人掌图【仙人掌】
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1023 [题解] 仙人掌入门题,拿圆方树练练手. 圆方树就是把一个环建一个新方点,然后向 ...
- ZZULIOJ Python题解1023: 大小写转换
ZZULIOJ题解 1023: 大小写转换 题目描述 输入一个字母,若是小写字母,则变为大写输出,否则,原样输出. 输入 输入为一个字符. 输出 按题目要求输出一个字符,单独占一行. 样例输入 a 样 ...
- PAT甲级1023 Have Fun with Numbers:[C++题解]高精度加法和两个vector大小比较
文章目录 题目分析 题目链接 题目分析 使用高精度加法高精度加法板子求 这个数的两倍,存在一个vector中. 所谓高精度就是使用string来存大的数,然后模拟列竖式加法,结果一位一位压入数组vec ...
- 浙大 pat 1023题解
1023. Have Fun with Numbers (20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...
- Woj 简易题解 Volume #2
*1101 数据范围太扯淡了..如果不考虑范围的话可以这样想,从一个点到另外一个点他们的哈密顿距离为他们的最短距离,那么这个距离的步数就是我需要的最少步数,假设从一个点到另外一个点要走m步,那么首先从 ...
- CodeChef Starters 26 Division 3 (Rated)----STNGAME(中文题解)
描述: Contest Page | CodeChef 上面是原题目的地址,简要概括一下意思:Alice和Bob在玩一个填字符串的游戏,一开始Alice有n个字符,Bob也有n个字符.他们需要用这些字 ...
- 2020ICPC·小米 网络选拔赛第一场 全部题解
整理的算法模板合集: ACM模板 目录 题目传送门 题目总体情况 A.Intelligent Warehouse B.Intelligent Robot C.Smart Browser D.Route ...
- Codeforces 1110 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 众所周知ldxoildxoildxoi这种菜鸡选手是不会写HHH题的,因此该篇博客只有AAA题至GGG题的题解,实在抱歉. A题 传送门 题 ...
- uva 725 Division(暴力模拟)
Division 紫书入门级别的暴力,可我还是写了好长时间 = = [题目链接]uva 725 [题目类型]化简暴力 &题解: 首先要看懂题意,他的意思也就是0~9都只出现一遍,在这2个5位数 ...
最新文章
- 计算机组成原理考研重点
- 初始化栈、入栈、出栈、栈空、数制转换函数和主函数,实现1348转换成8进制的功能。
- c c++常用算法手册(第3版_嵌入式软件开发必看书籍推荐(C/C++/linux/软件)
- java 数据聚合_Java数据聚合问题请教?
- 图片(img标签)的onerror事件,你有用过嘛?
- 博客入驻阿里“云栖社区”
- DL之pix2pix:基于TF利用pix2pix模型对food_resized数据集实现Auto Color自动上色技术—训练测试过程全记录
- NLP事件抽取综述(上中下):中文事件抽取、开放域事件抽取、事件数据生成、跨语言事件抽取、小样本事件抽取、零样本事件抽取等类型
- 最大值_285期 博最大值2路,已经箭在弦上!
- 分页池内存持续增长_鸿蒙内核源码分析(从进程/线程视角看内存)
- python eval 字符串替换_Python中eval妙用,字符串转字典和列表
- ORACLE中BFILE字段的使用研究
- 福州:物联网产业加速集聚 每年安排不低于1000万元专项资金
- OpenCV 填充多边形 fillConvexPoly 和 fillPoly
- 漂亮的抽奖C#源代码
- Maven-Eclipse使用maven创建HelloWorld Java项目
- python Socket 客户端
- Idea的JShell Console
- steamcommunity本地反代443端口/80端口被占用解决办法
- 【MySQL】Mcafee审计插件