BZOJ 1048 [HAOI2007]分割矩阵

1048: [HAOI2007]分割矩阵

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 623  Solved: 449
[ Submit][ Status][ Discuss]

Description

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

Input

 第一行为3个整数,表示a,b,n(1<a,b<=10,1<n<=10)的值。

第二行至第n+1行每行为b个小于100的非负整数,表示矩阵中相应位置上的分值。每行相邻两数之间用一个空格分开。

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

HINT

 

Source

题解:数据好小,显然记忆化爆搜即可喽。。。

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!!多维数组是不能用sizeof赋值的!!!!!!!!!!!!!!!!!!!

!!!啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(' ')
 9 #define ENT putchar('\n')
10 using namespace std;
11 const int maxn=10+3,inf=-1u>>1;
12 double S[maxn][maxn],t[maxn][maxn][maxn][maxn][maxn],ve;
13 int n,m,k;
14 double sqr(double a){return a*a;}
15 double size(int x1,int y1,int x2,int y2){
16     return S[x2][y2]+S[x1-1][y1-1]-S[x2][y1-1]-S[x1-1][y2];
17 }
18 double dfs(int x1,int y1,int x2,int y2,int k){
19     double&now=t[x1][y1][x2][y2][k];
20     if(now!=-1)return now;
21     if(!k)return (now=sqr(size(x1,y1,x2,y2)-ve));now=1e9;
22     for(int i=x1;i<x2;i++)
23         for(int j=0;j<k;j++)
24             now=min(now,dfs(x1,y1,i,y2,j)+dfs(i+1,y1,x2,y2,k-j-1));
25     for(int i=y1;i<y2;i++)
26         for(int j=0;j<k;j++)
27             now=min(now,dfs(x1,y1,x2,i,j)+dfs(x1,i+1,x2,y2,k-j-1));
28     return now;
29 }
30 inline int read(){
31     int x=0,sig=1;char ch=getchar();
32     for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0;
33     for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
34     return sig?x:-x;
35 }
36 inline void write(int x){
37     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
38     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
39     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
40 }
41 int main(){
42     n=read();m=read();k=read();
43     for(int a=0;a<=10;a++)
44     for(int b=0;b<=10;b++)
45     for(int c=0;c<=10;c++)
46     for(int d=0;d<=10;d++)
47     for(int l=0;l<=10;l++)
48     t[a][b][c][d][l]=-1;
49     for(int i=1;i<=n;i++)
50         for(int j=1;j<=m;j++)
51             S[i][j]=S[i-1][j]+S[i][j-1]-S[i-1][j-1]+(double)read();
52     ve=S[n][m]/k;
53     dfs(1,1,n,m,k-1);
54     printf("%.2lf",sqrt(t[1][1][n][m][k-1]/k));
55     return 0;
56 }
57 /*
58 4 4 1
59 1 4 2 3 
60 1 5 3 3
61 -1 6 3 3
62 2 5 2 1
63 1 1 2 3
64 */

 

转载于:https://www.cnblogs.com/chxer/p/4727798.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值