pku1191 棋盤分割 DP

簡單的枚舉切法然後記憶化更新

時間複雜度嗯……n^m?其實要小的多,然而好像只能這樣寫

Problem: 1191		User: BPM136
Memory: 1500K		Time: 16MS
Language: G++		Result: Accepted

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 10
#define inf 0x3f3f3f3f
int a[N][N];
int sum[N][N][N][N];
int f[20][N][N][N][N];
int n=8,m;

int add(int x1,int y1,int x2,int y2)
{
    int ans=0,x,y;
    fo(x,x1,x2)
        fo(y,y1,y2)
            ans+=a[x][y];
    return ans;
}

int dfs(int k,int x1,int y1,int x2,int y2)
{
	if(f[k][x1][y1][x2][y2]!=-1)
	return f[k][x1][y1][x2][y2];
	f[k][x1][y1][x2][y2]=inf;
	if(x1<x2)
	{
		fo(i,x1,x2-1)
		{
			int ret1=dfs(k-1,x1,y1,i,y2);
			int ret2=dfs(k-1,i+1,y1,x2,y2);
			int t1=sum[x1][y1][i][y2];
			int t2=sum[i+1][y1][x2][y2];
			int ret=min(ret1+t2*t2,ret2+t1*t1);
			f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],ret);
		}
	}
	if(y1<y2)
	{
		fo(j,y1,y2-1)
		{
			int ret1=dfs(k-1,x1,y1,x2,j);
			int ret2=dfs(k-1,x1,j+1,x2,y2);
			int t1=sum[x1][y1][x2][j];
			int t2=sum[x1][j+1][x2][y2];
			int ret=min(ret1+t2*t2,ret2+t1*t1);
			f[k][x1][y1][x2][y2]=min(f[k][x1][y1][x2][y2],ret);
		}
	}
	return f[k][x1][y1][x2][y2];
}

int main()
{
	memset(f,-1,sizeof(f));
	m=read();
	fo(i,1,n)
	{
		fo(j,1,n)
		{
			a[i][j]=read();
		}
	}
	fo(i,1,n)
	{
		fo(j,1,n)
		{
			fo(x,i,n)
			{
				fo(y,j,n)
				{
					int t;
					t=sum[i][j][x][y]=add(i,j,x,y);
					f[1][i][j][x][y]=t*t;
				}
			}
		}
	}
	double k=(double)dfs(m,1,1,8,8)/m;
	double average=sum[1][1][8][8]*1.0;
	average=(average/m)*(average/m);
	double ans=((double)k-average)*1.0;
	printf("%.3f\n",sqrt(ans));
	return 0;
}


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