poj1191——棋盘分隔

来源:互联网 发布:凤凰新闻数据库设计 编辑:程序博客网 时间:2024/06/05 17:31

题目大意:原棋盘上每一格有一个分值,一块矩形棋盘的总分为各格分值之和,用n-1次将棋盘切割成n块,使得各个棋盘总分的均方差O'最小

输入:n

           8*8的非负整数(表示棋盘上相应格子的分值)

输出:O'(四舍五入到小数点后三位)

分析:dfs+dp

           首先化简一下方差公式:

           ,也就是说将题目转化为求各个棋盘总分的平方和最小值。输入时预处理一下,在val[i][j]数组中存储的是(1,1)(i,j)这个棋盘的总分(ij这个小格子加上两部分再减去重叠部分)。

           动规的状态:dp(n,x1,y1,x2,y2)表示左上角(x1,y1)右上角(x2,y2)的棋盘被切割成n块时的最小平方和

           状态转移方程:

           nowstate=min( nowstate, dfs(k-1, x1, y1, a ,y2)+s[a+1, y1, x2, y2])

           nowstate=min( nowstate, dfs(k-1, a+1, y1, x2, y2)+s[x1, y1, a, y2])

           nowstate=min( nowstate, dfs(k-1, x1, b+1, x2, y2)+s[x1, y1, x2, b])

           nowstate=min( nowstate, dfs(k-1, x1, y1, x2, b)+s[x1, b+1, x2, y2])

代码:转载自https://www.cnblogs.com/CSU3901130321/p/3961415.html

1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 int dp[15][9][9][9][9],val[9][9],n; 8  9 int sum(int x1,int y1,int x2,int y2)10 {11     int ans=val[x2][y2]-val[x1-1][y2]-val[x2][y1-1]+val[x1-1][y1-1];//ans为(x1,y1)(x2,y2)这个矩形棋盘的总分12     return ans*ans;13 }14 15 int dfs(int k,int x1,int y1,int x2,int y2)16 {17     if(dp[k][x1][y1][x2][y2]) return dp[k][x1][y1][x2][y2];18     if(k==1||x1==x2||y1==y2){19         dp[k][x1][y1][x2][y2]= sum(x1,y1,x2,y2);20         return dp[k][x1][y1][x2][y2];21     }22     int nowstate=INF;23     for(int i=x1;i<x2;i++){//横着切24         nowstate=min(nowstate,dfs(k-1,i+1,y1,x2,y2)+sum(x1,y1,i,y2));25         nowstate=min(nowstate,dfs(k-1,x1,y1,i,y2)+sum(i+1,y1,x2,y2));26     }27     for(int i=y1;i<y2;i++){//竖着切28         nowstate=min(nowstate,dfs(k-1,x1,i+1,x2,y2)+sum(x1,y1,x2,i));29         nowstate=min(nowstate,dfs(k-1,x1,y1,x2,i)+sum(x1,i+1,x2,y2));30     }31     dp[k][x1][y1][x2][y2]=nowstate;32     return nowstate;33 }34 35 void change()36 {37     for(int i=0;i<=8;i++)38         val[i][0]=0,val[0][i]=0;39 40     for(int i=1;i<=8;i++)41         for(int j=1;j<=8;j++)42             val[i][j]+=val[i-1][j]+val[i][j-1]-val[i-1][j-1];43 }44 45 int main()46 {47     while(~scanf("%d",&n)){48 49         memset(dp,0,sizeof(dp));50 51         for(int i=1;i<=8;i++)52             for(int j=1;j<=8;j++)53                 scanf("%d",&val[i][j]);54 55         change();56 57         double res;58         double ave=1.0*val[8][8]/n;59         res=sqrt((double)dfs(n,1,1,8,8)/n-ave*ave);60         printf("%.3f\n", res);61     }62     return 0;63 }

原创粉丝点击