poj1191(記憶化搜索)

1.這題的經典之處感覺不在記憶化搜索,而是在區域化的預處理,之前就碰到過好多這樣的題目了。

s[x1,y1,x2,y2]表示從(x1,y1)到(x2,y2)的面積,可以轉換爲s[x2,y2]-s[x1-1,y2]-s[x1,y2-1]+s[x1-1][y1-1];其中s[x2,y2]表示從(0,0)至(x2,y2)的面積


2.代碼(g++WA,c++AC),求解釋!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define MAX 1000000000
#define N 8//!!
#define M 10
using namespace std;
//   freopen("data.in","r",stdin);
int mat[M][M],s[M][M];
int ropow[M][M][M][M][15];
void prepare()
{
	int i,j;
    s[0][0]=mat[0][0];
    for(i=1; i<N; i++)
    {
        s[0][i]=s[0][i-1]+mat[0][i];//
        s[i][0]=s[i-1][0]+mat[i][0];
    }
    for(i=1; i<N; i++)
    {
        for(j=1; j<N; j++)
        {
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+mat[i][j];
        }
    }
}

int getArea(int x1,int y1,int x2,int y2)
{
    int sum=s[x2][y2];
    if(x1>0)sum-=s[x1-1][y2];
    if(y1>0)sum-=s[x2][y1-1];
    if(x1>0&&y1>0)sum+=s[x1-1][y1-1];
    return sum*sum;//
}

int dfs(int x1,int y1,int x2,int y2,int k)//x1<=x2,y1<=y2,k>=0
{
    if(ropow[x1][y1][x2][y2][k]!=-1)return ropow[x1][y1][x2][y2][k];
    if(k==0)return  ropow[x1][y1][x2][y2][k]=getArea(x1,y1,x2,y2);
    else if(x1==x2&&y1==y2)return ropow[x1][y1][x2][y2][k]=MAX;

	int i;
    ropow[x1][y1][x2][y2][k]=MAX;
    int tmp;
    for(i=x1; i<x2; i++)
    {
        tmp=dfs(x1,y1,i,y2,k-1)+getArea(i+1,y1,x2,y2);
        if(tmp<ropow[x1][y1][x2][y2][k])ropow[x1][y1][x2][y2][k]=tmp;
        tmp=getArea(x1,y1,i,y2)+dfs(i+1,y1,x2,y2,k-1);
        if(tmp<ropow[x1][y1][x2][y2][k])ropow[x1][y1][x2][y2][k]=tmp;
    }

    for(i=y1; i<y2; i++)
    {
        tmp=dfs(x1,y1,x2,i,k-1)+getArea(x1,i+1,x2,y2);
        if(tmp<ropow[x1][y1][x2][y2][k]) ropow[x1][y1][x2][y2][k]=tmp;

        tmp=getArea(x1,y1,x2,i)+dfs(x1,i+1,x2,y2,k-1);
        if(tmp<ropow[x1][y1][x2][y2][k])ropow[x1][y1][x2][y2][k]=tmp;
    }
    return ropow[x1][y1][x2][y2][k];
}
int main()
{
    //  freopen("data.in","r",stdin);
    int block;
    cin>>block;

    for(int i=0; i<N; i++)
    {
        for(int j=0; j<N; j++)cin>>mat[i][j];
    }

    prepare();

    memset(ropow,-1,sizeof(ropow));
    double ro2=dfs(0,0,N-1,N-1,block-1);//
    double tot=s[N-1][N-1];

    tot/=block;
    tot*=tot;
    double t=sqrt(ro2/block-tot );
    printf("%.3lf\n",t) ;
    return 0;
}


3.總結

1.狀態方程中用到加法,而上界用了INT_MAX,結果出現了負數------以後出現負數,注意是否越界!

2.把題目輸入的n當成切割次數,結果瞎調了半天!-------不知道錯了哪裏時就重新讀一啓遍題!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章