专栏文章

题解:P2258 [NOIP2014 普及组] 子矩阵

P2258题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miql0rtb
此快照首次捕获于
2025/12/04 06:32
3 个月前
此快照最后确认于
2025/12/04 06:32
3 个月前
查看原文

题目地址

题目使用 n3n^3 dp做法最佳
因为还要枚举从哪里转移过来
而对于 max/min\max / \min 的这种转移
一般还可以用单调队列优化dp使复杂度降一维
CPP
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
const int N=20;
int min=2147482647;
int map[N][N];
int qu[N];
int n,m,r,c;
int xx[N],yy[N][N];
int f[N][N];
void dp()
{
	memset(xx,0,sizeof(xx));
	memset(yy,0,sizeof(yy));
	memset(f,127,sizeof(f));
	for(int i=1;i<=m;i++)
	for(int j=2;j<=r;j++)
	xx[i]+=abs(map[qu[j]][i]-map[qu[j-1]][i]);
	
	for(int i=1;i<=m;i++)
	for(int j=i+1;j<=m;j++)
	for(int k=1;k<=r;k++)
	yy[i][j]+=abs( map[qu[k]][i]-map[qu[k]][j]);
	
	for(int i=1;i<=m;i++)	f[i][0]=0,f[i][1]=xx[i];
	
	for(int i=1;i<=m;i++)
	for(int j=2;j<=c;j++)
	{
		for(int k=1;k<i;k++)
		f[i][j]=std::min(f[i][j],f[k][j-1]+yy[k][i]+xx[i]);
	}
	for(int i=1;i<=m;i++)
	min=std::min(min,f[i][c]);
}
void dfs(int i,int step)
{
	if(step==r+1)	
	{
		dp();
		return;
	}
	if(n-i<r-step)	return;
	for( ;i<=n;i++)	
	qu[step]=i,dfs(i+1,step+1);
}
int main()
{
	scanf("%d %d %d %d",&n,&m,&r,&c);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	scanf("%d",&map[i][j]);
	dfs(1,1);
	printf("%d\n",min);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...