洛谷P2258 子矩阵——题解




表示一开始也是一脸懵逼
,虽然想到了DP,但面对多变的状态不知从何转移及怎么合理记录状态。之(借鉴大佬思路)后,豁然开朗,于是在AC后分享一下题解。
发现数据范围出奇地小,不过越是小的数据范围,算法的灵活性就越大。小数据对我们各个算法的组合及时间复杂度的掌握要求很高。面对二维的最优化选择,其实我们可以先通过搜索枚举出行的所有选择,存到一个数组team中,然后在行已经确认的情况下,跑一遍一维的DP:设dp[j][i]为在前j列选择i列的最优情况(为了方便,要求第i选择的列一定是第j列)。则状态转移方程就可写成:dp[j][i]=min(dp[j][i],dp[k][i-1]+lc[j]+hc[k][j]),其中lc为第j列的分值,hc[k][j]为第k列和第j列横向相邻元素对分值的贡献,k=i-1,i-1+1,...,j-1。对于lc和hk
我们可以在每次搜索完成后预处理一下,整个程序的时间复杂度即为O(C(n,r)*rm2),足以解出题。
代码上有一个小优化,详情见注释:
#include <iostream>
#include <cstdio>
#include <cmath> using namespace std; int n, m, r, c, num[][], ans = 0x7fffffff, team[], lteam;
int lc[]; //列
int hc[][]; //列之间
int dp[][]; void init()
{
for (int i = ; i <= m; i++)
{
lc[i] = ;
for (int j = ; j < r; j++)
lc[i] += abs(num[team[j]][i] - num[team[j + ]][i]);
}
for (int i = ; i < m; i++)
for (int j = i + ; j <= m; j++)
{
hc[i][j] = ;
for (int k = ; k <= r; k++)
hc[i][j] += abs(num[team[k]][i] - num[team[k]][j]);
}
} void DP()
{
for (int i = ; i <= m; i++)
dp[i][] = lc[i];
if (c == )
{
for (int i = ; i <= m; i++)
ans = ans > dp[i][] ? dp[i][] : ans;
return;
}
for (int i = ; i <= c; i++)
{
for (int j = i; j <= m - c + i; j++)
{
dp[j][i] = 0x2fffffff;
for (int k = j - ; k >= i - ; k--)
dp[j][i] = min(dp[j][i], dp[k][i - ] + lc[j] + hc[k][j]);
}
}
for (int i = c; i <= m; i++)
ans = min(ans, dp[i][c]);
} void dfs(int now)
{
if (now > n)//选择完毕
{
init();
DP();
return;
}
if (r - lteam == n - now + )//当剩下的元素与还要选择的元素的数量相等时,必须要选
{
team[++lteam] = now;
dfs(now + );
--lteam;
return;
}
dfs(now + );//当前行要么不选
if (lteam < r)//要么在符合条件的情况下选
{
team[++lteam] = now;
dfs(now + );
--lteam;
}
} int main()
{
scanf("%d%d%d%d", &n, &m, &r, &c);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
scanf("%d", &num[i][j]);
dfs();
printf("%d", ans);
return ;
}
洛谷P2258 子矩阵——题解的更多相关文章
- 洛谷P2258 子矩阵 题解 状态压缩/枚举/动态规划
作者:zifeiy 标签:状态压缩.枚举.动态规划 题目链接:https://www.luogu.org/problem/P2258 这道题目状态压缩是肯定的,我们需要用二进制来枚举状态. 江湖上有一 ...
- 洛谷 P2258 子矩阵 解题报告
P2258 子矩阵 题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第 2 . 4行和第 ...
- 洛谷P2258 子矩阵
P2258 子矩阵 题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4 ...
- 洛谷 P2258 子矩阵
题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...
- 洛谷P2258 子矩阵[2017年5月计划 清北学堂51精英班Day1]
题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...
- 洛谷NOIp热身赛题解
洛谷NOIp热身赛题解 A 最大差值 简单树状数组,维护区间和.区间平方和,方差按照给的公式算就行了 #include<bits/stdc++.h> #define il inline # ...
- 洛谷P2827 蚯蚓 题解
洛谷P2827 蚯蚓 题解 题目描述 本题中,我们将用符号 ⌊c⌋ 表示对 c 向下取整. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现 ...
- 洛谷P1816 忠诚 题解
洛谷P1816 忠诚 题解 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人 ...
- [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)
[POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...
随机推荐
- Android - Android 面试题集
1.Java部分 1.1 操作系统相关 1.什么是操作系统? 2.什么是线程,什么是进程? 1.2 JDK&JVM&JRE 1.JDK & JVM & JRE分别是什么 ...
- Go语言入门篇-基本类型排序和 slice 排序
参见博客:https://blog.csdn.net/u010983881/article/details/52460998 package main import ( "sort" ...
- ubuntu 虚拟机安装
ubuntu16.04.5 LTS 安装 1.下载ubuntu镜像 打开ubuntu官网镜像地址https://launchpad.net/ubuntu/+cdmirrors 在上面中搜索chin ...
- 获取程序所有加载的dll名称
1.在任务管理器输入如下指令.输出到文件:tasklist /m >c:\dll.txt 输出到命令行 tasklist /m 2.使用工具软件https://files.cnblogs.com ...
- 循环结构 :for
循环结构 :for 循环四要素: 1.初始化条件 2.循环条件 3.循环体 4.迭代条件 格式: for(初始化条件;循环条件;迭代条件){ 循环体; } 执行顺序 :1 -> 2 -> ...
- 【7.24校内交流赛】T3【qbxt】复读警告
数据范围:N,key<=1000; 首先看题目背景,显然不是DP就是图论,但是这显然不是个图论,因此这就是个DP: 接下来考虑怎么DP 我们定义dp[i][j]表示现在dp到了第i个数,当前i个 ...
- catch that cow POJ 3278 搜索
catch that cow POJ 3278 搜索 题意 原题链接 john想要抓到那只牛,John和牛的位置在数轴上表示为n和k,john有三种移动方式:1. 向前移动一个单位,2. 向后移动一个 ...
- linux中断处理上下部分
一.linux中断处理为什么要分为上下部 1.1. 中断处理的上半部(top half,又叫顶半部)和处理的下半部(bottom half,又叫底半部) 1.1. linux中断处理不参与调度,故中断 ...
- vue项目如何监听窗口变化,达到页面自适应?
[自适应]向来是前端工程师需要解决的一大问题--即便作为当今非常火热的vue框架,也无法摆脱--虽然elementui.iview等开源UI组件库层出不穷,但官方库毕竟不可能满足全部需求,因此我们可以 ...
- 什么是lambda函数?有什么好处?
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的匿名函数 好处:1.lambda 函数比较轻便,即用即删除,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都 ...