bzoj3810: [Coci2015]Stanovi(记忆化搜索)

  实际上切出来的矩阵在原矩阵上的位置是不重要的。。。重要的只有矩阵的大小和上下左右是否在边界上。

  于是我们可以设f[x][y][l][r][u][d]表示x*y的矩阵上下左右是不是边界的最小代价。

  记忆化搜索一下横着切和竖着切。

  但是这样会被卡。。我们令x>=y l>=r u>=d可以减少很多相同的状态数,而且答案是不变的,这样常数小很多才能过

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio> 
#include<algorithm>
#define ll long long 
using namespace std;
const int maxn=310;
int n,m,k;
ll f[maxn][maxn][2][2][2][2];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
ll dfs(int x,int y,int l,int r,int u,int d)
{
    if(x<y)swap(x,y),swap(l,d),swap(u,r);
    if(u<d)swap(u,d);if(l<r)swap(l,r);
    if(f[x][y][l][r][u][d]!=-1)return f[x][y][l][r][u][d];
    ll ans=1ll*(x*y-k)*(x*y-k);
    if(l||r||(u&&d))for(int i=1;i<x;i++)ans=min(ans,dfs(i,y,l,r,u,0)+dfs(x-i,y,l,r,0,d));
    if(u||d||(l&&r))for(int i=1;i<y;i++)ans=min(ans,dfs(x,i,l,0,u,d)+dfs(x,y-i,0,r,u,d));
//    printf("%d %d %d %d %d %d %d\n",x,y,l,r,u,d,ans);
    return f[x][y][l][r][u][d]=ans;
}
int main()
{
    read(n);read(m);read(k);
    memset(f,-1,sizeof(f));
    printf("%lld\n",dfs(n,m,1,1,1,1));
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Sakits/p/7626988.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值