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;
}

 

posted @ 2018-02-27 18:41  柳暗花明_liu  阅读(153)  评论(0编辑  收藏  举报