题目大意:给定一个 N*M 的矩阵,现从 N 行中选出 R 行,M 列中选出 C 列,构成一个 R*C 子矩阵,求这个子矩阵相邻元素差的绝对值之和的最小值是多少。
题解:
发现是对行和列的组合生成,若直接暴力的话,时间复杂度为 \(O({n \choose r}{m \choose c}nm)\)。
代码如下
#include
using namespace std;
const int maxn=20;
int n,m,r,c,ans,mp[maxn][maxn];
vector row,col;
inline void calc(){
int ret=0;
for(int i=0;ic||col.size()+m-now+1r||row.size()+n-now+1
进一步考虑,发现若枚举出了 r 行,那么对于每一列来说,可以抽象成下列问题,即:给定一个长度为 N 的序列,现从序列中选出 M 个元素组成的子序列,使得这 M 个元素中相邻两个元素差的绝对值之和最小。发现是一个 dp,对于矩阵来说,将矩阵转化成序列即可,dp 的时间复杂度为 \(O(n^3)\)。总的时间复杂度为 \(O({n \choose r}m^3)\)。
代码如下
#include
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=20;
int n,m,r,c,ans,mp[maxn][maxn];
vector row;
int dp[maxn][maxn],extra[maxn],cost[maxn][maxn];
inline void calc(){
cls(dp,0x3f),cls(extra,0),cls(cost,0);
for(int i=1;i<=m;i++)for(int j=i+1;j<=m;j++)for(auto ro:row)cost[i][j]+=abs(mp[ro][i]-mp[ro][j]);
for(int co=1;co<=m;co++)for(int i=0;ir||row.size()+n-now+1