【动态规划+递归】:poj1191,棋盘分割

来源:互联网 发布:部队网络保密心得体会 编辑:程序博客网 时间:2024/06/06 00:25

http://poj.org/problem?id=1191



明白几点:

1)最终的均方差可以转变成:sqrt( sigma[ i:1-m ]( xi*xi ) / n - ( sum(all) / n )*( sum(all) / n ) ),不懂这个转换的需要补一下数学基础;所以最终决定最小值的是sigma[ i:1-m ]( xi*xi )。

2)动归含义:

dp[n][x1][x2][y1][y2]
表示由x1,x2,y1,y2组成的矩形要生成n块小矩阵,均方差的最小值(sigma[ i:1-m ]( xi*xi ));它的值需要遍历所有横向切、纵向切的可能,然后取最小值。最终结果是dp[n][1][8][1][8],不多说。




# include<iostream># include<string.h># include<cmath>using namespace std;# define N 16# define INF 1000000000int data[9][9];int dp[N][9][9][9][9];int onePart[9][9][9][9];int OnePart(int x1, int x2, int y1, int y2){int sum=0;for(int x=x1;x<=x2;x++){for(int y=y1;y<=y2;y++){sum+=data[x][y];}}return sum;}int Partition(int n, int x1, int x2, int y1, int y2){if(dp[n][x1][x2][y1][y2]!=-1){return dp[n][x1][x2][y1][y2];}else{int x,y,t,t1,t2;dp[n][x1][x2][y1][y2]=INF;//up-downfor(x=x1;x<x2;x++) //x<x2, not x<=x2{//continue partition upt1=onePart[x+1][x2][y1][y2]+Partition(n-1,x1,x,y1,y2); //onePart[x+1][x2][y1][y2], not onePart[x][x2][y1][y2]//continue partition downt2=onePart[x1][x][y1][y2]+Partition(n-1,x+1,x2,y1,y2);t = t1<t2? t1:t2 ;dp[n][x1][x2][y1][y2] = dp[n][x1][x2][y1][y2]<t? dp[n][x1][x2][y1][y2]:t ;}//left-rightfor(y=y1;y<y2;y++){//continue partition leftt1=onePart[x1][x2][y+1][y2]+Partition(n-1,x1,x2,y1,y);//continue partition rightt2=onePart[x1][x2][y1][y]+Partition(n-1,x1,x2,y+1,y2);t = t1<t2? t1:t2 ;dp[n][x1][x2][y1][y2] = dp[n][x1][x2][y1][y2]<t? dp[n][x1][x2][y1][y2]:t ;}return dp[n][x1][x2][y1][y2];}}int main(){int x1,x2,y1,y2,x,y,n,t;int sum=0;cin>>n;for(x=1;x<=8;x++){for(y=1;y<=8;y++){cin>>data[x][y];sum+=data[x][y];}}memset(dp,-1,sizeof(dp));for(x1=1;x1<=8;x1++){for(x2=x1;x2<=8;x2++){for(y1=1;y1<=8;y1++){for(y2=y1;y2<=8;y2++){t=OnePart(x1,x2,y1,y2);onePart[x1][x2][y1][y2]=t*t;dp[1][x1][x2][y1][y2]=t*t;}}}}Partition(n,1,8,1,8);printf("%.3f\n",  sqrt( dp[n][1][8][1][8]*1.0/n - (sum*1.0/n)*(sum*1.0/n) )  );return 0;}


1 0
原创粉丝点击