[HAOI2007]分割矩阵
06年一道均分数据的随机化,07年的这道题又是划分,又是方差最小。话说我第一眼看到懵了一下,二维随机化???
然而这道题是矩阵,且是一刀一刀切割的,应该是DP,但是我也没啥思路。
正解是记忆化搜索吧,搜索说好打也好打,但是不好调啊,要注意细节。
本题可以用 f[a][b][c][d][k] 表示把左下 (a,b),右上 (c,d) 的矩形切 k 刀的最优解。
对每一步有两种切割方式。
1:横切。分成 (a,b) & (c,i) 和 (a,i+1) & (c,d) 两个矩形。
2:竖切。分成 (a,b) & (i,d) 和 (i+1,b) & (c,d) 两个矩形。
再有需要注意的一点是状态中还有一维 k ,所以在切完这一刀后,还要枚举给两个矩形分别再切几刀。
搜索是基本功啊。
// q.c #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int MAX=12; int n,m,k,w[MAX][MAX],s[MAX][MAX]; double ave,f[MAX][MAX][MAX][MAX][MAX]; double cal(double x) { return x*x; } double dfs(int a,int b,int c,int d,int p) { double &g=f[a][b][c][d][p]; if(g!=-1) return g; if(!p) return g=cal(s[c][d]-s[a-1][d]-s[c][b-1]+s[a-1][b-1]-ave); g=1e9; for(int i=a;i<c;i++) for(int j=0;j<p;j++) g=min(g,dfs(a,b,i,d,j)+dfs(i+1,b,c,d,p-j-1)); for(int i=b;i<d;i++) for(int j=0;j<p;j++) g=min(g,dfs(a,b,c,i,j)+dfs(a,i+1,c,d,p-j-1)); return g; } int main() { freopen("separation.in","r",stdin); freopen("separation.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int a=1;a<=n;a++) for(int b=1;b<=m;b++) for(int c=a;c<=n;c++) for(int d=b;d<=m;d++) for(int e=0;e<k;e++) f[a][b][c][d][e]=-1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&w[i][j]); 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]+w[i][j]; ave=s[n][m]*1.0/k; dfs(1,1,n,m,k-1); printf("%.2lf\n",sqrt(f[1][1][n][m][k-1]/k)); return 0; }