觉得题目水的离开
觉得普及组垃圾的请离开
不知道 DFS 和 DP 的请离开
不屑的大佬请离开
…….
感谢您贡献的访问量

————————————————华丽的分割线 ————————————————

先看题面:

题目描述
给出如下定义:
子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵。
例如,下面左图中选取第2、4行和第2、4、5列交叉位置的元素得到一个2*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*3的子矩阵是
4 7 4
8 6 9
相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的。
矩阵的分值:矩阵中每一对相邻元素之差的绝对值之和。
本题任务:给定一个n行m列的正整数矩阵,请你从这个矩阵中选出一个r行c列的子矩阵,使得这个子矩阵的分值最小,并输出这个分值。
输入输出格式
输入格式:
第一行包含用空格隔开的四个整数n,m,r,c,意义如问题描述中所述,每两个整数之间用一个空格隔开。
接下来的n行,每行包含m个用空格隔开的整数,用来表示问题描述中那个n行m列的矩阵。
输出格式:
输出共1行,包含1个整数,表示满足题目描述的子矩阵的最小分值。
输入输出样例
输入样例#1:
5 5 2 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
输出样例#1:
6
输入样例#2:
7 7 3 3
7 7 7 6 2 10 5
5 8 8 2 1 6 2
2 9 5 5 6 1 7
7 9 3 6 1 7 8
1 9 1 4 7 8 8
10 5 9 1 1 8 10
1 3 1 5 4 8 6
输出样例#2:
16
说明
【输入输出样例1说明】
该矩阵中分值最小的2行3列的子矩阵由原矩阵的第4行、第5行与第1列、第3列、第4列交叉位置的元素组成,为
6 5 6
7 5 6
,其分值为|6−5| + |5−6| + |7−5| + |5−6| + |6−7| + |5−5| + |6−6| =6。
【输入输出样例2说明】
该矩阵中分值最小的3行3列的子矩阵由原矩阵的第4行、第5行、第6行与第2列、第6列、第7列交叉位置的元素组成,选取的分值最小的子矩阵为
9 7 8
9 8 8
5 8 10
【数据说明】
对于50%的数据,1 ≤ n ≤ 12,1 ≤ m ≤ 12,矩阵中的每个元素1 ≤ a[i][j] ≤ 20;
对于100%的数据,1 ≤ n ≤ 16,1 ≤ m ≤ 16,矩阵中的每个元素1 ≤ a[i][j] ≤ 1,000,
1 ≤ r ≤ n,1 ≤ c ≤ m。


思路:

对于50%的数据,太小了直接DFS强行求解就可以啦,然而优秀的oier显然不屑于这50分,我们要打正解。对于100%的数据1 ≤ n ≤ 16,1 ≤ m ≤ 16,DFS显然不能裸跑AC(尤其是在NOIP评测机上),直接DP也不怎么好写,所以正解就是DFS + DP。只要DFS选哪一行 O(2 ^ n),再加一个DP O(n^3)求选了这些行的最小子矩阵的值即可。
用f[i][j]表示选了i列,最后一列为j的最小子矩阵的值,w[i]表示第i列,行与行之间的绝对值和,v[i][j]表示第i列到第j列的列与列之间的绝对值和,然后DP即可。

看代码

  1. # include <stdio.h>
  2. # include <stdlib.h>
  3. # include <string.h>
  4. # include <iostream>
  5. # include <math.h>
  6. using namespace std;
  7. # define mem(a, b) memset(a, b, sizeof(a))
  8. # define N 20
  9. # define RG register
  10. # define IL inline
  11. # define ll long long
  12. # define oo 2147483647
  13. # define max(a, b) ((a) > (b)) ? (a) : (b)
  14. # define min(a, b) ((a) < (b)) ? (a) : (b)
  15. IL int Get(){
  16. RG char c = '!'; RG int num = 0, z = 1;
  17. while(c != '-' && (c < '0' || c > '9')) c = getchar();
  18. if(c == '-') z = -1, c = getchar();
  19. while(c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar();
  20. return num * z;
  21. }
  22. int n, m, r, c, a[N][N], w[N], ans = oo, x[N], f[N][N], v[N][N];
  23. IL void DP(){
  24. mem(v, 0); mem(f, 127); mem(w, 0);
  25. for(RG int i = 1; i <= m; i++)
  26. for(RG int j = 1; j < r; j++)
  27. w[i] += abs(a[x[j]][i] - a[x[j + 1]][i]);
  28. for(RG int i = 1; i <= m; i++)
  29. for(RG int j = i + 1; j <= m; j++)
  30. for(RG int k = 1; k <= r; k++)
  31. v[i][j] += abs(a[x[k]][i] - a[x[k]][j]);
  32. f[0][0] = 0;
  33. for(RG int i = 1; i <= c; i++)
  34. for(RG int j = i; j <= m; j++)
  35. for(RG int k = 0; k < j; k++)
  36. f[i][j] = min(f[i][j], f[i - 1][k] + w[j] + v[k][j]);
  37. for(RG int i = c; i <= m; i++)
  38. ans = min(ans, f[c][i]);
  39. }
  40. IL void Dfs(RG int t, RG int pre){
  41. if(t > r){
  42. DP();
  43. return;
  44. }
  45. for(RG int i = pre + 1; n - i >= r - t; i++){
  46. x[t] = i;
  47. Dfs(t + 1, i);
  48. }
  49. }
  50. int main(){
  51. n = Get(); m = Get(); r = Get(); c = Get();
  52. for(RG int i = 1; i <= n; i++)
  53. for(RG int j = 1; j <= m; j++)
  54. a[i][j] = Get();
  55. Dfs(1, 0);
  56. printf("%d\n", ans);
  57. return 0;
  58. }

本蒟蒻还是初学者,如有写的不好请见谅

2014NOIP普及组 子矩阵的更多相关文章

  1. [NOIP2014普及组]子矩阵

    题目:洛谷P2258.Vijos P1914.codevs 3904. 题目大意:给你一个矩阵,要你找一个r行c列的子矩阵,求最小分值(子矩阵和分值的定义见原题). 解题思路:n和m比较小,考虑暴力. ...

  2. NOIP2002-2017普及组题解

    虽然普及组一般都是暴力省一,但是有一些题目还是挺难的qwq个人觉得能进TG的题目会在前面打上'*' NOIP2002(clear) #include<bits/stdc++.h> usin ...

  3. NOIP2012 普及组 T3 摆花——S.B.S.

    题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...

  4. NOIP2016普及组复赛解题报告

    提高组萌新,DAY1DAY2加起来骗分不到300,写写普及组的题目聊以自慰. (附:洛谷题目链接 T1:https://www.luogu.org/problem/show?pid=1909 T2:h ...

  5. 05:统计单词数【NOIP2011复赛普及组第二题】

    05:统计单词数 总时间限制:  1000ms 内存限制:  65536kB 描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次 ...

  6. [题解]noip2016普及组题解和心得

    [前言] 感觉稍微有些滑稽吧,毕竟每次练的题都是提高组难度的,结果最后的主要任务是普及组抱一个一等奖回来.至于我的分数嘛..还是在你看完题解后写在[后记]里面.废话不多说,开始题解. 第一题可以说的内 ...

  7. NOIP2016普及组

    普及组.代码有空发. 第一题就是买铅笔.暴力模拟绝对可取. 第二题就是回文日期.从t1的年份到t2的年份枚举每一年.头尾要特判. 第三题就是海港.骗了40分. 第四题就是魔法阵.不太好优化. 完.

  8. [NOIP2013] 普及组

    计数问题 纯模拟 #include<cstdio> #include<iostream> using namespace std; int main(){ int n,x; c ...

  9. NOIP2008 普及组T2 排座椅 解题报告-S.B.S

    题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳.同学 ...

随机推荐

  1. 异步请求时有时会让js不起作用,那么重新加载js

    function reloadSmartMenu() { var jsElem = document.createElement('script'); jsElem.src= path+'/syste ...

  2. Java集合中的Map接口

    jdk1.8.0_144 Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap.TreeMap.So ...

  3. ubuntu16.04 python3 安装selenium及环境配置

    环境 ubuntu16.04 python3 安装selenium sudo pip3 install seleium 默认安装完是支持firefox,但是更新得太慢对于较新的firefox已经不支持 ...

  4. Nuget发布自己的DLL

          首先说明背景,在asp.net core开发中,使用了Oracle,Oracle官方发布了一个新的sdk用于连接数据库,但是asp.net core有个特性,就是不支持直接引用dll,也就 ...

  5. Laravel框架中Form表单Get请求搜索(在此感谢[https://simon8.com])

    首先看一下HTML部分的Form表单 <form role="search" method="get" id="searchform" ...

  6. 重温基础之-css盒模型

    所有html元素都可以看作盒子. css盒模型本质上是一个盒子,封装周围的html元素,它包括:外边距,边框,内边距和实际内容. 默认情况下,一个元素的总宽度计算方式: 总宽度=左外边距+左边框+左内 ...

  7. golang调试工具Delve

    Devle是一个非常棒的golang 调试工具,支持多种调试方式,直接运行调试,或者attach到一个正在运行中的golang程序,进行调试. 线上golang服务出现问题时,Devle是必不少的在线 ...

  8. ERROR 1045 (28000): Access denied for user xxx & ERROR 1449 (HY000): The user specified as a definer xxx does not exists

    今天在一个修改过权限的MySQL数据库遇到了"ERROR 1045 (28000): Access denied for user 'xxx'@'xxx.xxx.xxx.xxx' (usin ...

  9. Android设置View抖动动画

    在应用中,有时候我们要吸引用户去点击某些按钮,比如应用市场的推荐按钮,为了能够吸引用户主动点击而且不过分的打扰用户,最好的方法就是给我们想吸引用户注意的view添加一些抖动动画,比如这张图 这里我主要 ...

  10. 【php】curl常见的错误号和解释

    curl 错误代码列表 CURLE_UNSUPPORTED_PROTOCOL (1) – 您传送给 libcurl 的网址使用了此 libcurl 不支持的协议. 可能是您没有使用的编译时选项造成了这 ...