简单的枚举切法然后记忆化更新
时间复杂度嗯……n^m?其实要小的多,然而好像只能这样写
Problem: 1191 User: BPM136
Memory: 1500K Time: 16MS
Language: G++ Result: Accepted
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 10
#define inf 0x3f3f3f3f
int a[N][N];
int sum[N][N][N][N];
int f[20][N][N][N][N];
int n=8,m;
int add(int x1,int y1,int x2,int y2)
{
int ans=0,x,y;
fo(x,x1,x2)
fo(y,y1,y2)
ans+=a[x][y];
return ans;
}
int dfs(int k,int x1,int y1,int x2,int y2)
{
if(f[k][x1][y1][x2][y2]!=-1)
return f[k][x1][y1][x2][y2];
f[k][x1][y1][x2][y2]=inf;
if(x1<x2)
{
fo(i,x1,x2-1)
{
int ret1=dfs(k-1,x1,y1,i,y2);
int ret2=dfs(k-1,i+1,y1,x2,y2);
int t1=sum[x1][y1][i][y2];
int t2=sum[i+1][y1][x2][y2];
int ret=min(ret1+t2*t2,ret2+t1*t1);
f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],ret);
}
}
if(y1<y2)
{
fo(j,y1,y2-1)
{
int ret1=dfs(k-1,x1,y1,x2,j);
int ret2=dfs(k-1,x1,j+1,x2,y2);
int t1=sum[x1][y1][x2][j];
int t2=sum[x1][j+1][x2][y2];
int ret=min(ret1+t2*t2,ret2+t1*t1);
f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],ret);
}
}
return f[k][x1][y1][x2][y2];
}
int main()
{
memset(f,-1,sizeof(f));
m=read();
fo(i,1,n)
{
fo(j,1,n)
{
a[i][j]=read();
}
}
fo(i,1,n)
{
fo(j,1,n)
{
fo(x,i,n)
{
fo(y,j,n)
{
int t;
t=sum[i][j][x][y]=add(i,j,x,y);
f[1][i][j][x][y]=t*t;
}
}
}
}
double k=(double)dfs(m,1,1,8,8)/m;
double average=sum[1][1][8][8]*1.0;
average=(average/m)*(average/m);
double ans=((double)k-average)*1.0;
printf("%.3f\n",sqrt(ans));
return 0;
}