DP--POJ1191 棋盘分割
分析:
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> using namespace std; int s[9][9],MIN; //MIN是一个陷阱 可以去掉 千万不能把MIN在fun函数中做全局变量来用,会GG int sum[9][9]; int res[15][9][9][9][9]; int r_sum(int x1,int y1,int x2, int y2){ //求任意矩形内所有数之和 return sum[x2][y2]+sum[x1-1][y1-1]-sum[x2][y1-1]-sum[x1-1][y2]; } int fun(int n,int x1,int y1,int x2,int y2){ //以x1,y1和x2,y2构成的 内含n个矩形 的矩形其“内部各个矩形的数字和的平方 的和”最小值 int i,l,tp,z,y,s,x,MIN=100000000; if( res[n][x1][y1][x2][y2]!=-1 ) return res[n][x1][y1][x2][y2]; if(n==1){ int l1=r_sum(x1,y1,x2,y2); res[n][x1][y1][x2][y2]=l1*l1; return l1*l1; } for(i=x1;i<x2;i++){ //纵切,留左留右哪个好? z=r_sum(x1,y1,i,y2); y=r_sum(i+1,y1,x2,y2); tp=min(y*y+fun(n-1,x1,y1,i,y2),z*z+fun(n-1,i+1,y1,x2,y2) ); if( tp<MIN ) MIN=tp; } for(l=y1;l<y2;l++){ //横切,留上留下哪个好? s=r_sum(x1,y1,x2,l); x=r_sum(x1,l+1,x2,y2); tp=min(s*s+fun(n-1,x1,l+1,x2,y2),x*x+fun(n-1,x1,y1,x2,l) ); if( tp<MIN ) MIN=tp; // 四种切法哪个好? } res[n][x1][y1][x2][y2]=MIN; //最好的 return MIN; } int main(){ // freopen("in.txt","r",stdin); memset(sum,0,sizeof(sum)); memset(res,-1,sizeof(res)); int n,i_sum; cin>>n; for(int i=1;i<=9;i++){ i_sum=0; for(int j=1;j<9;j++){ cin>>s[i][j]; i_sum+=s[i][j]; //第i行前j个数之和 sum[i][j]+=sum[i-1][j]+i_sum; //1,1到i,j矩形内的所有数之和 } } // cout<<sum[1][1]<<' '<<sum[4][4]<<' '<<sum[8][8]<<endl; // cout<<fun(n,1,1,8,8)<<endl; double result=n*fun(n,1,1,8,8)-sum[8][8]*sum[8][8]; printf("%.3f\n",sqrt(result/(n*n))); return 0; }
柳暗花明又一村