POJ 1191 棋盘分割 (记忆化搜索)

来源:互联网 发布:网络电视转换数字电视 编辑:程序博客网 时间:2024/05/16 17:20

题意:

思路:先要对公式化简,我的数学好差,花了好长时间化简。然后用记忆化搜索,dp[d][x1][y1][x2][y2] 存储 把大小为(x1,y1)(x2,y2)的矩阵分成d份的最小值。。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <stack>using namespace std;const int INF = 0x7ffffff;int dp[16][9][9][9][9];int map[9][9];int n,ans,sum;int dfs(int dep,int x1,int y1,int x2,int y2){    if(dp[dep][x1][y1][x2][y2]>=0)        return dp[dep][x1][y1][x2][y2];    int ans=INF;    for(int i=x1;i<x2;i++)    {        int t=dfs(dep-1,i+1,y1,x2,y2)+dp[1][x1][y1][i][y2];        ans = min(t,ans);        t = dfs(dep-1,x1,y1,i,y2)+dp[1][i+1][y1][x2][y2];        ans = min(t,ans);    }    for(int i=y1;i<y2;i++)    {        int t=dfs(dep-1,x1,i+1,x2,y2)+dp[1][x1][y1][x2][i];        ans = min(t,ans);        t = dfs(dep-1,x1,y1,x2,i)+dp[1][x1][i+1][x2][y2];        ans = min(t,ans);    }    dp[dep][x1][y1][x2][y2] = ans;    return ans;}int oor(int x1,int y1,int x2,int y2){    int ans=0;    for(int i=x1;i<=x2;i++)    for(int j=y1;j<=y2;j++)    ans+=map[i][j];    return ans;}void init(){    for(int i=0;i<8;i++)    for(int k=i;k<8;k++)    for(int j=0;j<8;j++)    for(int l=j;l<8;l++)    {        dp[1][i][j][k][l]=oor(i,j,k,l);        dp[1][i][j][k][l]=dp[1][i][j][k][l]*dp[1][i][j][k][l];    }}int main(){    freopen("in.txt","r",stdin);    scanf("%d",&n);    memset(dp,-1,sizeof(dp));    for(int i=0;i<8;i++)    for(int j=0;j<8;j++)    scanf("%d",&map[i][j]),sum+=map[i][j];    init();    ans=dfs(n,0,0,7,7);    printf("%.3lf\n",sqrt((ans-1.0*sum/n*sum)/n));    return 0;}