# 1048: [HAOI2007]分割矩阵

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

F(a,b,c,d)左端点(a,c)右端点(b,d)之间的区间和。记忆化会快一点...
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
double MIN(double di,double ck){
if(di<ck)return di;
return ck;}
const double INT=1e9+7;
int an=0,f=1;char ch=getchar();
while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
while('0'<=ch&&ch<='9'){an=an*10+(ch-'0');ch=getchar();}
return an*f;
}
int e[20][20],sum,K,n,m;
double Q,dp[20][20][20][20][20],ans;
bool rem[20][20][20][20][20];
int F(int a,int b,int c,int d){
int ff=0;
for(int i=a;i<=b;i++)
for(int j=c;j<=d;j++)ff+=e[i][j];
return ff;
}
double dfs(int a,int b,int c,int d,int k){
double re=INT;
if(rem[a][b][c][d][k])return dp[a][b][c][d][k];
if(k==0){
re=F(a,b,c,d)-Q;
re=re*re;
dp[a][b][c][d][k]=re;
rem[a][b][c][d][k]=1;
return re;}
for(int i=a+1;i<=b;i++)
for(int j=0;j<k;j++)
re=MIN(re,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++)
re=MIN(re,dfs(a,b,c,i-1,j)+dfs(a,b,i,d,k-j-1));
dp[a][b][c][d][k]=re;
rem[a][b][c][d][k]=1;
return re;
}
int main(){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
sum+=e[i][j];}
Q=(double)(sum)/K;
ans=dfs(1,n,1,m,K-1);
printf("%0.2f",sqrt(ans/K));
return 0;
}
2217

by:s_a_b_e_r

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double inf=1e9;
int a,b,n;
double num[15][15],f[15][15][15][15][15],sum[15][15],ave;
double cal(int xx,int yy,int x,int y)
{return sum[x][y]-sum[xx-1][y]-sum[x][yy-1]+sum[xx-1][yy-1];}
double dfs(int xx,int yy,int x,int y,int k)
{
if(f[xx][yy][x][y][k]>=0)return f[xx][yy][x][y][k];
if(k==0)
{
double ret=cal(xx,yy,x,y)-ave;
return f[xx][yy][x][y][k]=ret*ret;
}
else
{
double ret=inf;
for(int i=xx;i<x;++i)
for(int j=0;j<k;++j)
ret=min(ret,dfs(xx,yy,i,y,j)+dfs(i+1,yy,x,y,k-1-j));
for(int i=yy;i<y;++i)
for(int j=0;j<k;++j)
ret=min(ret,dfs(xx,yy,x,i,j)+dfs(xx,i+1,x,y,k-1-j));
return f[xx][yy][x][y][k]=ret;
}
}
int main()
{
scanf("%d%d%d",&a,&b,&n);
for(int i=1;i<=a;++i)
for(int j=1;j<=b;++j)
{
scanf("%lf",&num[i][j]);
sum[i][j]=sum[i][j-1]+num[i][j];
}
for(int i=1;i<=a;++i)
for(int j=1;j<=b;++j)
sum[i][j]+=sum[i-1][j];
ave=sum[a][b]/double(n);
memset(f,-1,sizeof(f));
double ans=dfs(1,1,a,b,n-1);
printf("%.2f",sqrt(ans/double(n)));
return 0;
}
1084

s:开学了的说,要死了啊啊
w:开学快乐x
posted @ 2017-08-30 16:16  ck666  阅读(210)  评论(0编辑  收藏  举报