洛谷 P2258 子矩阵 解题报告
P2258 子矩阵
题目描述
给出如下定义:
子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵。
例如,下面左图中选取第 2 、 4行和第 2 、 4 、5 列交叉位置的元素得到一个 \(2 \times 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 3\)的子矩阵是
4 7 4
8 6 9
相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的。
矩阵的分值:矩阵中每一对相邻元素之差的绝对值之和。
本题任务:给定一个\(n\)行\(m\)列的正整数矩阵,请你从这个矩阵中选出一个\(r\)行\(c\)列的子矩阵,使得这个子矩阵的分值最小,并输出这个分值。
(本题目为2014NOIP普及T4)
输入输出格式
输入格式:
第一行包含用空格隔开的四个整数\(n,m,r,c\) ,意义如问题描述中所述,每两个整数之间用一个空格隔开。
接下来的\(n\)行,每行包含\(m\)个用空格隔开的整数,用来表示问题描述中那个\(n\)行\(m\)列的矩阵。
输出格式:
一个整数,表示满足题目描述的子矩阵的最小分值。
数据说明
对于\(50\%\)的数据, \(1≤n≤12,1≤m≤12\),矩阵中的每个元素\(1 ≤ a_{ij} ≤ 20\);
对于\(100\%\)的数据,\(1 ≤ n ≤ 16,1 ≤ m ≤ 16\),矩阵中的每个元素\(1 ≤ a_{ij} ≤ 1,000,1 ≤ r ≤ n,1 ≤ c ≤ m\)。
感觉这个题不难想,但不知道为什么做了好久啊。
数据很小,想到状压
但我们发现每一行的排布是一样的,那就不状压了
搜索每一行的排列,即从某一行选择哪些列
然后对选择哪些行做背包即可
复杂度:\(O(C_m^cn^2(c+r))\)
Code:
#include <cstdio>
#include <cstring>
int min(int x,int y){return x<y?x:y;}
int abs(int x){return x>0?x:-x;}
const int N=17;
int dp[N][N],n,m,r,c,g[N][N],cho[N],cal[N][N],cal0[N],ans=0x3f3f3f3f;
void init()
{
memset(cal,0,sizeof(cal));
memset(cal0,0,sizeof(cal0));
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=1;k<=c;k++)
cal[i][j]+=abs(g[i][cho[k]]-g[j][cho[k]]);
for(int i=1;i<=n;i++)
for(int k=2;k<=c;k++)
cal0[i]+=abs(g[i][cho[k]]-g[i][cho[k-1]]);
}
void work()
{
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=r;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<j;k++)
dp[i][j]=min(dp[i][j],dp[i-1][k]+cal[k][j]+cal0[j]);
for(int i=1;i<=n;i++)
ans=min(ans,dp[r][i]);
}
void dfs(int dep,int s)
{
if(dep==c+1)
{
init();
work();
return;
}
int rr=m+dep-c;
for(int i=s;i<=rr;i++)
{
cho[dep]=i;
dfs(dep+1,i+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",&g[i][j]);
dfs(1,1);
printf("%d\n",ans);
return 0;
}
2018.7.28
洛谷 P2258 子矩阵 解题报告的更多相关文章
- 洛谷 P2058 海港 解题报告
P2058 海港 题目描述 小K是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客. 小K对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况: ...
- 洛谷 P3956 棋盘 解题报告
P3956 棋盘 题目描述 有一个\(m×m\)的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的(不能 ...
- 洛谷 P1979 华容道 解题报告
P1979 华容道 题目描述 小\(B\)最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...
- BZOJ 3545 / 洛谷 P4197 Peaks 解题报告
P4197 Peaks 题目描述 在\(\text{Bytemountains}\)有\(N\)座山峰,每座山峰有他的高度\(h_i\).有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个 ...
- 洛谷P2258 子矩阵
P2258 子矩阵 题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4 ...
- 虔诚的墓主人(BZOJ1227)(洛谷P2154)解题报告
题目描述 小W是一片新造公墓的管理人.公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. 当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地. ...
- 洛谷 P2258 子矩阵
题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...
- 洛谷P2258 子矩阵[2017年5月计划 清北学堂51精英班Day1]
题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素 ...
- 洛谷P2258 子矩阵 题解 状态压缩/枚举/动态规划
作者:zifeiy 标签:状态压缩.枚举.动态规划 题目链接:https://www.luogu.org/problem/P2258 这道题目状态压缩是肯定的,我们需要用二进制来枚举状态. 江湖上有一 ...
随机推荐
- Adobe Photoshop CC2018最新教程+某宝店铺装修教程
PS免费教程,ps淘宝店铺装修教程.该资源为本人从某商网站重金买来,现免费分享给大家,下载地址:百度网盘,https://pan.baidu.com/s/127PjFbGwVVUVce1litHFsw
- Postman 高级用法指南
Postman是一款强大的API接口测试工具,有许多不容易发现的好用的功能,下面简单介绍其中一部分功能.详细内容可以参考文档,官方还有视频教程,非常方便入手.后续本博客会持续提供一些Postman使用 ...
- 在Android上运用Anko和Kotlin开发数据库:SQLite从来不是一件轻松的事(KAD25)
作者:Antonio Leiva 时间:Mar 30, 2017 原文链接:https://antonioleiva.com/databases-anko-kotlin/ 事实告诉我们:在Androi ...
- Unity初探之黑暗之光(1)
Unity初探之黑暗之光(1) 1.镜头拉近 public float speed=10f;//镜头的移动速度 ;//镜头的结束位置 // Update is called once per fram ...
- jetbrains系列激活
没钱,只能DB了. 为了避免某些个人私自搭建服务器,以及自己搭建激活服务器,因此,决定使用破解包~~~. 注意:只要破解,就要屏蔽官方激活服务器:0.0.0.0 account.jetbrains.c ...
- Elasticsearch 相同内容文档,不同score(评分)的奇怪问题
原文:http://stackoverflow.com/questions/14580752/elasticsearch-gives-different-scores-for-same-documen ...
- Python3 异常与断言
1.异常 当出现错误时,程序就会发生异常 num1=input('Please input a num1: ') num2=input('Please input a num2: ') print(f ...
- Python函数的内省-Introspection
Python函数可以进行内省-Introspection,查看函数内部的细节,方式就是使用函数的__code__属性. def func(a, b = 2): return a + b >> ...
- default & delete
一.使用“=default” 1. 显式生成拷贝控制成员的合成版本 class A { public: A() = default; A(const A &) = default; A& ...
- 拷贝构造函数 & 拷贝赋值运算符
一.拷贝构造函数 1. 形式 class A { public: // ... A(const A &); // 拷贝构造函数 }; 2. 合成拷贝构造函数 编译器总会为我们合成一个拷贝构造函 ...