您的位置:首页 > 其它

poj 1191 棋盘分割 dp

2013-04-14 19:38 471 查看
记忆化搜索

dp[x1][y1][x2][y2]
表示把该区域的棋盘分成n份的最优解

状态转移

把棋盘沿着x或者y轴切割成成两块,然后选择一块分成n-1块

这里刚开始用的是dp[][][][][]!=inf来表示搜索过该点,但是这个程序会搜索出一些无法分解成n份的棋盘

此时解的初始值不会被更改,导致出现错误,最后超时,所以,一定要注意细节

#include <iostream>

#include<stdio.h>

#include<string.h>

#include<math.h>

using namespace std;

const int maxn=10;

const int inf=199999999;

int a[maxn][maxn];

int dp[maxn][maxn][maxn][maxn][20];

int sum[maxn][maxn][maxn][maxn];

int text[maxn][maxn][maxn][maxn][20];

int time=0;

int min(int a,int b)

{

if(a<b) return(a);

return(b);

}

int dfs(int x1,int y1,int x2,int y2,int n)

{

//
printf("%d\n",n);

if(text[x1][y1][x2][y2]
) return(0);

time++;

if(n==1)

{

dp[x1][y1][x2][y2][1]=(sum[x1][y1][x2][y2])*(sum[x1][y1][x2][y2]);

return(0);

}

for(int
i=x1;i<x2;i++)

{

int k=1;

//dfs(x1,y1,i,y2,k);

dp[x1][y1][i][y2][1]=(sum[x1][y1][i][y2])*(sum[x1][y1][i][y2]);

if(dp[i+1][y1][x2][y2][n-k]==inf)

dfs(i+1,y1,x2,y2,n-k);

dp[x1][y1][x2][y2]
=min(dp[x1][y1][x2][y2]
,dp[x1][y1][i][y2][k]+dp[i+1][y1][x2][y2][n-k]);

k=n-1;

if(dp[x1][y1][i][y2][k]==inf)

dfs(x1,y1,i,y2,k);

dp[i+1][y1][x2][y2][1]=(sum[i+1][y1][x2][y2])*(sum[i+1][y1][x2][y2]);

dp[x1][y1][x2][y2]
=min(dp[x1][y1][x2][y2]
,dp[x1][y1][i][y2][k]+dp[i+1][y1][x2][y2][n-k]);

}

for(int
i=y1;i<y2;i++)

{

int k=1;

dp[x1][y1][x2][i][k]=sum[x1][y1][x2][i]*sum[x1][y1][x2][i];

if(dp[x1][i+1][x2][y2][n-k])

dfs(x1,i+1,x2,y2,n-k);

dp[x1][y1][x2][y2]
=min(dp[x1][y1][x2][y2]
,dp[x1][y1][x2][i][k]+dp[x1][i+1][x2][y2][n-k]);

k=n-1;

if(dp[x1][y1][x2][i][k]==inf)

dfs(x1,y1,x2,i,k);

dp[x1][i+1][x2][y2][1]=sum[x1][i+1][x2][y2]*sum[x1][i+1][x2][y2];

dp[x1][y1][x2][y2]
=min(dp[x1][y1][x2][y2]
,dp[x1][y1][x2][i][k]+dp[x1][i+1][x2][y2][n-k]);

}

text[x1][y1][x2][y2]
=1;

//
if(dp[x1][y1][x2][y2]
==inf)

// {

//
printf("%d %d %d %d %d\n",x1,y1,x2,y2,n);

//
getchar();

// }

return(0);

}

int main()

{

int n;

scanf("%d",&n);

for(int
i=1;i<=8;i++)

for(int
j=1;j<=8;j++)

scanf("%d",&a[i][j]);

for(int
i=1;i<=8;i++)

for(int
j=1;j<=8;j++)

for(int
p=1;p<=8;p++)

for(int
q=1;q<=8;q++)

for(int
k=1;k<=n;k++)

dp[i][j][p][q][k]=inf;

for(int
k=1;k<=8;k++)

for(int
i=1;i<=8;i++)

{

sum[k][i][k][i]=a[k][i];

for(int j=i+1;j<=8;j++)

sum[k][i][k][j]=sum[k][i][k][j-1]+a[k][j];

}

for(int
k=1;k<=8;k++)

for(int
i=1;i<=8;i++)

for(int
j=i;j<=8;j++)

for(int
t=k+1;t<=8;t++)

{

sum[k][i][t][j]=sum[k][i][t-1][j]+sum[t][i][t][j];

//
printf("%lf\n",sum[k][i][t][j]);

}

// for(int
i=2;i<=8;i++)

// for(int
j=2;j<=8;j++)

// printf("%d
%d %lf\n",i,j,sum[2][2][i][j]);

dfs(1,1,8,8,n);

for(int
i=1;i<=8;i++)

for(int
j=1;j<=8;j++)

for(int
p=1;p<=8;p++)

for(int
q=1;q<=8;q++)

for(int
k=1;k<=n;k++)

if(dp[i][j][p][q][k]==inf) ;

// printf("%d
%d %d %d %d\n",i,j,p,q,k);

double
ans=dp[1][1][8][8]
;

double
are=(double)sum[1][1][8][8]/(double)n;

are*=are;

ans/=(double)n;

ans-=are;

ans=sqrt(ans);

printf("%0.3f\n",ans);

//
printf("%d\n",time);

return
0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: