[洛谷P2258][NOIP2014PJ]子矩阵(dfs)(dp)
NOIP 2014普及组 T4(话说一道PJ组的题就把我卡了一个多小时诶)
这道题在我看第一次的时候是没有意识到这是一道DP题的,然后就摁着DFS敲了好长时间,结果敲了一个TLE
这是DP!!!
下面开始进入正题
题目描述
给出如下定义:
- 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵。
例如,下面左图中选取第22、44行和第22、44、55列交叉位置的元素得到一个2 \times 32×3的子矩阵如右图所示。
9 3 3 3 9
9 4 8 7 4
1 7 4 6 6
6 8 5 6 9
7 4 5 6 1
的其中一个2 \times 32×3的子矩阵是
4 7 4
8 6 9
相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的。
矩阵的分值:矩阵中每一对相邻元素之差的绝对值之和。
本题任务:给定一个nn行mm列的正整数矩阵,请你从这个矩阵中选出一个rr行cc列的子矩阵,使得这个子矩阵的分值最小,并输出这个分值。
输入输出格式
输入格式:
第一行包含用空格隔开的四个整数n,m,r,cn,m,r,c,意义如问题描述中所述,每两个整数之间用一个空格隔开。
接下来的nn行,每行包含mm个用空格隔开的整数,用来表示问题描述中那个nn行mm列的矩阵。
输出格式:
一个整数,表示满足题目描述的子矩阵的最小分值。
样例:
输入
输出
这道题就是将题目所给你的矩阵进行“选取”行与列的操作,从而得到所求的最大值的集合,但是重要的是我们不知道题目所给的行和列的值是多少,因此我们可以对此进行一个循环中的判断操作,在选出来这个行之后再去考虑列的情况,从而得出最优决策。
这个地方还有一个降维操作,就是我们在一个r * m(事先以及决定了选取那几行,该去考虑列的问题时)的矩阵中选取c列,这个时候我们可以把二维降低到一维,(因为这其中行已经有了判断的标准,我们只需要进行列的操作就足够了).
下面开始讲DP过程:
我们设f[i][j]表示在这个r*m的矩阵中,在其前i列中选择j列(且选的列中包括第i列),组成的子矩阵中,最小值(即其相邻元素的差的绝对值的和的最小值(之后的值等表达也是指的这个东西,即题目要求求出的值))是多少。
这样,推出状态转移方程如下:
f[i][j] = min (f[k][j-1] + hc[i][k] + lc[i])
下面就都是一些细节上的优化,代码里面已经讲的很清楚了。
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,r,c,gs=,minn=0x7fffffff,cmin; //不可能选取0列
int a[][];
int ch[],hc[][],lc[]; //hc[i][j] 对于第i列与第j列之间,所有同一行元素的差的绝对值的和
//lc[i]指的是第i列中所有元素的值
//ch[]是在dfs过程的数组
int f[][];
void init() //初始化
{
for(int i=;i<=m;i++)
{
lc[i] = ;
for(int j=;j<r;j++)
lc[i] += abs(a[ch[j]][i] - a[ch[j + ]][i]); //注意是+=
}
for(int i=;i<=m;i++)
{
for(int j=;j<i;j++) //注意j<i
{
hc[i][j] = ; //注意初始化
for(int k=;k<=r;k++)
hc[i][j] += abs(a[ch[k]][i] - a[ch[k]][j]); //注意是+=
}
}
}
void dp()
{
for(int i=;i<=m;i++)
{
cmin = min(i,c);
for(int j=;j<=cmin;j++)
{
if(j == ) //这个边界是只选取一列,就把元素赋进去就好
f[i][j] = lc[i];
else
if(j == i) //这个边界是前i列都需要选取
f[i][j] = f[i - ][j - ] + lc[i] + hc[i][j - ];
else
{
f[i][j] = 0x7fffffff; //注意初始化
for(int k=j-;k<i;k++)
f[i][j] = min(f[i][j],f[k][j - ] + lc[i] + hc[i][k]); //取最小值
}
if(j == c) //如果这种状态存在,那我们就更新一下
minn = min(minn,f[i][c]);
}
}
}
void dfs(int rt)
{
if(rt > n) //
{
init();
dp();
return ;
}
if(r - gs + == n - rt + ) //敲黑板!
/*
这个地方是一个剪枝,主要优化在了果rt和rt以后的元素必须全部取完,才能满足刚好有r个的条件,
则必须rt,否则便会取到少于r个元素的情况。
这样我们保证了rt > n时所有情况都刚好有r个,
*/
{
ch[gs++] = rt; //注意是gs++而不是++gs
dfs(rt + );
ch[gs--] = ; //注意是gs--而不是--gs
return ;
}
dfs(rt + );
if(gs <= r) //如果已经选取满了
{
ch[gs++] = rt; //但是还是需要这一步
dfs(rt + );
ch[gs--] = ;
}
}
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",&a[i][j]); //输入初始矩阵
dfs(); //开始搜索
printf("%d",minn); //答案已经被更新,输出就行
return ;
}
[洛谷P2258][NOIP2014PJ]子矩阵(dfs)(dp)的更多相关文章
- 【洛谷P2258】子矩阵
子矩阵 题目链接 搜索枚举选了哪几行,将DP降为一个一维的问题, 先预处理出w[i]表示该列上下元素差的绝对值之和 v[i][j]为第i列和第j列对应元素之差的绝对值之和 f[i][j]表示前j列中选 ...
- 题解 洛谷P2258 【子矩阵】
应该很容易想到暴力骗分. 我们考虑暴力\(dfs\)枚举所有行的选择,列的选择,每次跑一遍记下分值即可. 时间复杂度:\(O(C_n^r \times C_m^c \times r \times c) ...
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- NOIP2014 T4 子矩阵 dfs+dp
最近在狂补题啊QAQ... 打算先把NOIP的干掉吧... 点我看题 链接还是放洛谷的了... 题意:给一个n*m的矩阵,在这个矩阵里选 r 行 c 列,然后这 r 行 c 列所相交的格子为新矩阵的, ...
- 洛谷 P2392 kkksc03考前临时抱佛脚, dp / 深搜
题目链接 P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目 dp代码 #include <iostream> #includ ...
- 洛谷2344 奶牛抗议(DP+BIT+离散化)
洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- 洛谷P1541 乌龟棋(四维DP)
To 洛谷.1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游 ...
- 【洛谷】P1052 过河【DP+路径压缩】
P1052 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙 ...
随机推荐
- ubuntu 14.04 软件中心闪退解决方案
法一: gksudo gedit /usr/share/software-center/softwarecenter/ui/gtk3/views/lobbyview.py 注释下面这句话(注释使用#号 ...
- python3之协程
1.协程的概念 协程,又称微线程,纤程.英文名Coroutine. 线程是系统级别的它们由操作系统调度,而协程则是程序级别的由程序根据需要自己调度.在一个线程中会有很多函数,我们把这些函数称为子程序, ...
- keras例子-matchnet
2015CVPR:MatchNet_ Unifying Feature and Metric Learning for Patch-Based Matching 主要是基于patch的图像特征匹配,基 ...
- 分布式系列 - dubbo服务telnet命令【转】
dubbo服务发布之后,我们可以利用telnet命令进行调试.管理.Dubbo2.0.5以上版本服务提供端口支持telnet命令,下面我以通过实例抛砖引玉一下: 1.连接服务 测试对应IP和端口下的d ...
- Ajax+json+jquery实现无限瀑布流布局
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- eclipse自动编译
自动编译:对java应用没有什么意义,对web应用来说,当修改了代码时,会自动帮你编译并发布到web容器中去,省的重启web容器了. build:编译,Eclipse的编译是基于时间戳的判断机制的.c ...
- C# 文件拖放
将控件的属性AllowDrop设置为true,然后添加DragDrop.DragEnter时间处理函数 private void FormMain_DragEnter(object sender, D ...
- apache服务器的常用功能及设置
安装httpd yum -y install httpd 服务脚本:/etc/rc.d/init.d/httpd 脚本配置文件:/etc/sysconfig/httpd ...
- PYTHON-基本数据类型-数字类型,字符串类型,列表类型-练习
# 字符串练习# 写代码,有如下变量,请按照要求实现每个功能 (共6分,每小题各0.5分)# name = " aleX"# # 1) 移除 name 变量对应的值两边的空格,并输 ...
- bert中的分词
直接把自己的工作文档导入的,由于是在外企工作,所以都是英文写的 chinese and english tokens result input: "我爱中国",tokens:[&q ...