bzoj3810: [Coci2015]Stanovi(记忆化搜索)
2024-10-19 03:36:34
实际上切出来的矩阵在原矩阵上的位置是不重要的。。。重要的只有矩阵的大小和上下左右是否在边界上。
于是我们可以设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=;
int n,m,k;
ll f[maxn][maxn][][][][];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',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]!=-)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=;i<x;i++)ans=min(ans,dfs(i,y,l,r,u,)+dfs(x-i,y,l,r,,d));
if(u||d||(l&&r))for(int i=;i<y;i++)ans=min(ans,dfs(x,i,l,,u,d)+dfs(x,y-i,,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,-,sizeof(f));
printf("%lld\n",dfs(n,m,,,,));
return ;
}
最新文章
- How To Install Proxmox Nested on VMware ESXi (Full Support OpenVZ &; KVM)
- mysql-advanced-5.6.23-linux-glibc2.5-x86_64安装
- C++中的复制、赋值、析构
- Linux命令(1)-创建文件
- sql语句中charindex的用法 可用于截取字符串
- uestc 1720无平方因子数
- 1054. The Dominant Color (20)
- Airbnb创始人:屌丝的逆袭之路
- Azure 虚拟机常见问题-上
- Windows 中JDK安装配置教程
- arm汇编:ldr,str,ldm,stm,伪指令ldr
- Pro Android 4 第五章 理解Intent
- Centos使用dd命令制作U盘启动盘 wodim刻录光盘
- php第二季
- 简单实现contentOS下开机自动启动tomcat
- 重置studio 3T 14天试用
- Angular四大核心特性
- LeetCode(122):卖股票的最佳时机 II
- redis的一命令
- java集合类List