POJ 1191 棋盤分割 (記憶化搜尋)__動態規劃

來源:互聯網
上載者:User
Description

將一個8*8的棋盤進行如下分割:將原棋盤割下一塊矩形棋盤並使剩下部分也是矩形,再將剩下的部分繼續如此分割,這樣割了(n-1)次後,連同最後剩下的矩形棋盤共有n塊矩形棋盤。(每次切割都只能沿著棋盤格子的邊進行)

原棋盤上每一格有一個分值,一塊矩形棋盤的總分為其所含各格分值之和。現在需要把棋盤按上述規則分割成n塊矩形棋盤,並使各矩形棋盤總分的均方差最小。

均方差 σ=∑ni=1(xi−x¯)2n−−−−−−−−−√ σ=\sqrt{\frac{\sum^n_{i=1}{(x_i-\overline{x})^2}}{n}} ,其中平均值 x¯=∑ni=1xin \overline{x}=\frac{\sum^n_{i=1}{x_i}}{n} ,xi為第i塊矩形棋盤的總分。

請編程對給出的棋盤及n,求出O’的最小值。


Input

第1行為一個整數n(1 < n < 15)。

第2行至第9行每行為8個小於100的非負整數,表示棋盤上相應格子的分值。每行相鄰兩數之間用一個空格分隔。


Output

僅一個數,為O’(四捨五入精確到小數點後三位)。


Sample Input

31 1 1 1 1 1 1 31 1 1 1 1 1 1 11 1 1 1 1 1 1 11 1 1 1 1 1 1 11 1 1 1 1 1 1 11 1 1 1 1 1 1 11 1 1 1 1 1 1 01 1 1 1 1 1 0 3


Sample Output

1.633


思路

首先對方差公式進行化簡,化簡之後為 σ2=∑ni=1x2in−x¯2 σ^2=\frac{\sum^n_{i=1}{x_i^2}}{n}-\overline{x}^2

然後使用dfs搜尋時進行切割, dp[x][y][a][b][k] 代表進行 n-k 次切割以後矩陣 (x,y)-(a,b) 分值和的平方。

因為平均數是定值,要使方差最小,只能讓各塊的和儘可能的小。


AC 代碼

#include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<math.h>#include<iostream>using namespace std;#include<queue>#include<map>#define INF (1<<25)int n,sum[10][10];int dp[10][10][10][10][16];int get(int x,int y,int a,int b){    return sum[a][b]-sum[a][y-1]-sum[x-1][b]+sum[x-1][y-1];}int dfs(int x,int y,int a,int b,int k){    if(dp[x][y][a][b][k]!=-1)return dp[x][y][a][b][k];  //記憶化搜尋    if(k==1)return (dp[x][y][a][b][k]=get(x,y,a,b)*get(x,y,a,b));   //返回當前塊的和的平方    int minn=INF;    for(int i=x; i<a; i++)  //水平切割    {        int l=get(x,y,i,b);        int r=get(i+1,y,a,b);        minn=min(minn,min(dfs(x,y,i,b,k-1)+r*r,dfs(i+1,y,a,b,k-1)+l*l));    }    for(int i=y; i<b; i++)  //垂直切割    {        int l=get(x,y,a,i);        int r=get(x,i+1,a,b);        minn=min(minn,min(dfs(x,y,a,i,k-1)+r*r,dfs(x,i+1,a,b,k-1)+l*l));    }    return (dp[x][y][a][b][k]=minn);}int main(){    while(~scanf("%d",&n))    {        int temp;        memset(sum,0,sizeof(sum));        memset(dp,-1,sizeof(dp));        for(int i=1; i<=8; i++)            for(int j=1; j<=8; j++)            {                scanf("%d",&temp);                sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+temp;   //從(1,1)到(i,j)地區和            }        double avi=sum[8][8]*1.0/n;        printf("%.3f\n",sqrt(dfs(1,1,8,8,n)*1.0/n-avi*avi));    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.