POJ1191 棋盘分割 ACM解题报告(DFS+DP)

来源:互联网 发布:网络大电影误入歧途 编辑:程序博客网 时间:2024/03/29 02:26

最近期末复习,不能多刷题,只能每天A一个吧,今天还是深搜,这题比前两次的简单,不需要简直,只要DP即可,首先看这题目挺吓人的,我一开始也是二用了8个形参,结果DP根本无法记录,后来发现里面的3个居然是重复的,写完后就是不能过sample,对着百度的代码仔细检查,发现了居然每种情况更新最小值写在了循环外,也是基本功渣啊。

本题其实不难,就是记录切割后的矩形的坐标即可,然后开始棋盘上每块矩形的和必须打表计算,还有就是化简表达式,化简均方差的表达式得根号下sigma(xi)^2/n-ave^2,就会简单很多。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int a[10][10],sum[10][10],dp[16][10][10][10][10],n;int summ(int x1,int x2,int y1,int y2){    return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];//计算每块切割后舍弃的矩形的和,画图看会比较清晰}int dfs(int dao,int row1,int row2,int col1,int col2){    int temp,s1,s2,m=100000000;    if(dp[dao][row1][row2][col1][col2]!=-1) return dp[dao][row1][row2][col1][col2];//DP记录    if(dao==n-1)//n块就是n-1刀    {        s1=summ(row1,row2,col1,col2);        return dp[dao][row1][row2][col1][col2]=s1*s1;    }    for(int i=row1;i<row2;i++)    {        s1=summ(i+1,row2,col1,col2);        s2=summ(row1,i,col1,col2);        temp=min(s1*s1+dfs(dao+1,row1,i,col1,col2),s2*s2+dfs(dao+1,i+1,row2,col1,col2));        if(m>temp) m=temp;//犯二的地方,居然把这个写在了循环外我也是醉了。。。    }    for(int i=col1;i<col2;i++)    {        s1=summ(row1,row2,col1,i);        s2=summ(row1,row2,i+1,col2);        temp=min(s1*s1+dfs(dao+1,row1,row2,i+1,col2),s2*s2+dfs(dao+1,row1,row2,col1,i));        if(m>temp) m=temp;    }    return dp[dao][row1][row2][col1][col2]=m;}int main(){    int rev;    memset(sum,0,sizeof(sum));    memset(a,0,sizeof(a));    memset(dp,-1,sizeof(dp));    cin>>n;    for(int i=1; i<=8; i++)    {        for(int j=1; j<=8; j++)        {            scanf("%d",&a[i][j]);            sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j];//先计算每块顶点为(1,1)的矩形的和        }    }    rev=dfs(0,1,8,1,8);    //printf("%d ",rev);    double o;    o=sqrt(rev*1.0/n-sum[8][8]*sum[8][8]*1.0/(n*n));    printf("%.3lf\n",o);    return 0;}

0 0
原创粉丝点击