(记忆化搜索) bzoj 1048

1048: [HAOI2007]分割矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 502  Solved: 366
[Submit][Status]

Description

将一个a*b的数字矩阵进行如下分割:将原矩阵沿某一条直线分割成两个矩阵,再将生成的两个矩阵继续如此分割(当然也可以只分割其中的一个),这样分割了(n-1)次后,原矩阵被分割成了n个矩阵。(每次分割都只能沿着数字间的缝隙进行)原矩阵中每一位置上有一个分值,一个矩阵的总分为其所含各位置上分值之和。现在需要把矩阵按上述规则分割成n个矩阵,并使各矩阵总分的均方差最小。请编程对给出的矩阵及n,求出均方差的最小值。

Input

第一行为3个整数,表示a,b,n(1

Output

仅一个数,为均方差的最小值(四舍五入精确到小数点后2位)

Sample Input

5 4 4
2 3 4 6
5 7 5 1
10 4 0 5
2 0 2 3
4 1 1 1

Sample Output

0.50

水,

dp[1][n][1][m][k-1]这就是状态 再用个 二维 前缀和维护下就好啦。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<queue>
#include<cmath>
#include<algorithm>
#define inf 1000000000
#define ll long long
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
int n,m,K;
double ave;
int a[15][15];
int s[15][15];
double t[15][15][15][15][15];
double dfs(int a,int b,int c,int d,int k)
{
	double &res=t[a][b][c][d][k];
	if(res!=-1)return res;
	if(k==0)
	{
		res=s[b][d]+s[a-1][c-1]-s[a-1][d]-s[b][c-1];
		res=(res-ave)*(res-ave);
		return res;
	}
	res=1e9;
	for(int i=a+1;i<=b;i++)
		for(int j=0;j<k;j++)
			res=min(res,dfs(a,i-1,c,d,j)+dfs(i,b,c,d,k-j-1));
	for(int i=c+1;i<=d;i++)
		for(int j=0;j<k;j++)
			res=min(res,dfs(a,b,c,i-1,j)+dfs(a,b,i,d,k-j-1));
	return res;
}
int main()
{
	n=read();m=read();K=read();
	for(int a=0;a<=10;a++)
		for(int b=0;b<=10;b++)
			for(int c=0;c<=10;c++)
				for(int d=0;d<=10;d++)
					for(int l=0;l<=10;l++)
						t[a][b][c][d][l]=-1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			a[i][j]=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j],
	ave=(double)s[n][m]/K;
	dfs(1,n,1,m,K-1);
	printf("%.2lf",sqrt(t[1][n][1][m][K-1]/K));
	return 0;
}

  

时间: 2024-10-12 01:56:14

(记忆化搜索) bzoj 1048的相关文章

[BZOJ 1048] [HAOI2007] 分割矩阵 【记忆化搜索】

题目链接:BZOJ - 1048 题目分析 感觉这种分割矩阵之类的题目很多都是这样子的. 方差中用到的平均数是可以直接算出来的,然后记忆化搜索 Solve(x, xx, y, yy, k) 表示横坐标范围 [x, xx], 纵坐标范围 [y, yy] 的矩阵切成 k 块的最小 sigma((Vi - Ave)^2) . 然后再递归将矩阵分得更小,直到 k 为 1 的时候直接返回相应的值. 代码 #include <iostream> #include <cstdlib> #incl

[BZOJ 1055] [HAOI2008] 玩具取名 【记忆化搜索】

题目链接:BZOJ - 1055 题目分析 这种类似区间 DP 的记忆化搜索都是很相近的,比如字符串压缩和字符串扩展都差不多. 都是将现在 Solve 的区间分成子区间,再求解子区间. 这道题 Solve(l, r, x) 求能否将 [l, r] 的区间还原成 x ,那么就将它分成两段,看是否能左段变成 p , 右段变成 q. (x 能变成 pq) 代码 #include <iostream> #include <cstdio> #include <cstdlib> #

BZOJ 1079: [SCOI2008]着色方案 记忆化搜索

1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1079 Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&amp;&amp;NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床发现194了然后就各种刷--当我发现199的时候我决定把第200题交给05年NOI仅剩的一道题--结果尼玛调了能有一个小时--我居然没看到编号最小这个限制0.0 首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行单调递减 于是我们记忆化搜索 首先用

BZOJ 3895 取石子 博弈论+记忆化搜索

题目大意:给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 直接想很难搞,我们不妨来考虑一个特殊情况 假设每堆石子的数量都>1 那么我们定义操作数b为当前石子总数+当前堆数-1 若b为奇数,则先手必胜,否则后手必胜 证明: 若当前只有一堆,则正确性显然 否则: 若b为奇数,那么先手只需进行一次合成操作,此时操作数会-1,且仍不存在大小为1的堆 因此只需要证明b为偶数时先手必败即可 若先手选择了合成操作,那么操作数-1且不存在大小为1的堆,状态回到了b

【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路. 所有的路都是无向的,即

BZOJ 2656 ZJOI 2012 数列(sequence) 高精度+记忆化搜索

题目大意:定义个一序列,f[i] = f[i / 2] (i % 2 == 0);f[i] = f[i / 2] + f[i / 2 + 1] (i % 2 == 1);求这个数列的第m项(m <= 10 ^ 100) 思路:数据范围高精度没跑了.记得之前做过这个题的弱化版,似乎是没有高精度的记忆化搜索,这个题就是加个高精度. CODE: #include <map> #include <cstdio> #include <cstring> #include &l

BZOJ 2656 ZJOI2012 数列(sequence) 高精度+记忆化搜索

题目大意:给定一个数列的通项公式,求数列的某一项 高精度+记忆化搜索没说的 其实不用记忆化搜索的但是既然写完了就写完了吧 顺便学习了一下友元函数之类的东西- - #include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; class Big_Int{ private: int nu

BZOJ 3628 JLOI2014 天天酷跑 记忆化搜索

题意:...给定一个矩阵,每个点有一堆金币,自己在(0,1),然后各种跳,求最大收益(具体自己看) 传说中的省选第二题,当时写的爆搜20分,现在想想把深搜改成广搜再加个记忆化不就切了么...不过这题要开滚动数组 直接交MLE 正解应该是DP 我实在懒得DP就记忆化搜索了 反复memset那里常数有点大 懒得处理了 我自然溢出的队列居然写挂了...直接把h-1写在中括号里会强制类型转换成int导致调用q[-1] 所以只能这样了 交的人好少..这题也没啥意思 水水就切了 注意这题无论是数组还是读入输