博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
九度oj 题目1102:最小面积子矩阵
阅读量:4958 次
发布时间:2019-06-12

本文共 8909 字,大约阅读时间需要 29 分钟。

题目描述:

一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积)

输入:

每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K

接下来N行,每行M个数,表示矩阵每个元素的值

输出:

输出最小面积的值。如果出现任意矩阵的和都小于K,直接输出-1。

样例输入:
4 4 101 2 3 45 6 7 89 10 11 1213 14 15 16
样例输出:
1 这道题的题意读了半天才读懂,它是要求输出满足条件的最小的矩阵面积。 解决这类问题的重要办法就是降维,将二维降为一维。选取两列,将两列间元素相加,化为一维,再选取最小的大于k的最小连续长度 第一版代码是这样:
1 #include 
2 #include
3 #include
4 #include
5 #define MAX 102 6 7 int matrix[MAX][MAX]; 8 int tr[MAX]; 9 10 int main(int argc, char const *argv[])11 {12 int n, m, k;13 //freopen("input.txt","r",stdin);14 while(scanf("%d %d %d",&n, &m, &k) != EOF) {15 for(int i = 0; i < n; i++) {16 for(int j = 0; j < m; j++) {17 scanf("%d",&matrix[i][j]);18 }19 }20 21 int ans = n*m + 1;22 for(int i = 0; i < m; i++) {23 for(int j = i; j < m; j++) {24 //from i to j25 memset(tr,0,sizeof(tr));26 int ansij = -1;27 28 int base = j - i + 1;29 for(int h = 0; h < n; h++) {30 for(int q = i; q <= j; q++) {31 tr[h] = tr[h] + matrix[h][q];32 }33 }34 /*for(int h = 0; h < n; h++) {35 printf("%d ",tr[h]);36 }37 puts("");*/38 for(int len = 1; len <= n; len++) {39 for(int u = 0; u < n; u++) {40 int v = u + len -1;41 if(v >= n) {42 break;43 }44 int sum = 0;45 for(int w = u; w <= v; w++) {46 sum = sum + tr[w];47 }48 if(sum >= k) {49 ansij = len;50 break;51 }52 }53 if(ansij != -1) {54 break;55 }56 }57 if(ansij != -1 && ansij *base < ans) {58 ans = ansij*base;59 }60 }61 }62 if(ans < n*m+1) {63 printf("%d\n", ans);64 }65 else {66 puts("-1");67 }68 69 }70 return 0;71 }

时间为150ms

后来发现31行的累加很费时间,后来发现这个累加完全可以不用每回从头开始加,上一次的结果可以作为下一次的开始,代码修改为

1 #include 
2 #include
3 #include
4 #include
5 #define MAX 102 6 7 int matrix[MAX][MAX]; 8 int tr[MAX]; 9 10 int main(int argc, char const *argv[])11 {12 int n, m, k;13 //freopen("input.txt","r",stdin);14 while(scanf("%d %d %d",&n, &m, &k) != EOF) {15 for(int i = 0; i < n; i++) {16 for(int j = 0; j < m; j++) {17 scanf("%d",&matrix[i][j]);18 }19 }20 21 int ans = n*m + 1;22 for(int i = 0; i < m; i++) {23 memset(tr,0,sizeof(tr));24 for(int j = i; j < m; j++) {25 //from i to j26 int ansij = -1;27 28 int base = j - i + 1;29 for(int h = 0; h < n; h++) {30 tr[h] = tr[h] + matrix[h][j]; 31 32 }33 /*for(int h = 0; h < n; h++) {34 printf("%d ",tr[h]);35 }36 puts("");*/37 for(int len = 1; len <= n; len++) {38 for(int u = 0; u < n; u++) {39 int v = u + len -1;40 if(v >= n) {41 break;42 }43 int sum = 0;44 for(int w = u; w <= v; w++) {45 sum = sum + tr[w];46 }47 if(sum >= k) {48 ansij = len;49 break;50 }51 }52 if(ansij != -1) {53 break;54 }55 }56 if(ansij != -1 && ansij *base < ans) {57 ans = ansij*base;58 }59 }60 }61 if(ans < n*m+1) {62 printf("%d\n", ans);63 }64 else {65 puts("-1");66 }67 68 }69 return 0;70 }

时间为120ms

发现在45行仍有累加,修改为如下:

1 #include 
2 #include
3 #include
4 #include
5 #define MAX 102 6 7 int matrix[MAX][MAX]; 8 int tr[MAX]; 9 int dis[MAX][MAX];10 11 int cal(int u, int v) {12 if(dis[u][v] != 0) {13 return dis[u][v]; 14 }15 if(v == u) {16 dis[u][v] = tr[u];17 return dis[u][v];18 }19 else {20 dis[u][v] = dis[u][v-1] + dis[v][v];21 return dis[u][v-1] + dis[v][v];22 }23 }24 25 int main(int argc, char const *argv[])26 {27 int n, m, k;28 //freopen("input.txt","r",stdin);29 while(scanf("%d %d %d",&n, &m, &k) != EOF) {30 for(int i = 0; i < n; i++) {31 for(int j = 0; j < m; j++) {32 scanf("%d",&matrix[i][j]);33 }34 }35 36 int ans = n*m + 1;37 for(int i = 0; i < m; i++) {38 memset(tr,0,sizeof(tr));39 for(int j = i; j < m; j++) {40 //from i to j41 int ansij = -1;42 43 int base = j - i + 1;44 for(int h = 0; h < n; h++) {45 tr[h] = tr[h] + matrix[h][j]; 46 47 }48 /*for(int h = 0; h < n; h++) {49 printf("%d ",tr[h]);50 }51 puts("");*/52 memset(dis,0,sizeof(dis));53 54 for(int len = 1; len <= n; len++) {55 for(int u = 0; u < n; u++) {56 int v = u + len -1;57 if(v >= n) {58 break;59 }60 int sum = cal(u,v);61 if(sum >= k) {62 ansij = len;63 break;64 }65 }66 if(ansij != -1) {67 break;68 }69 }70 if(ansij != -1 && ansij *base < ans) {71 ans = ansij*base;72 }73 }74 }75 if(ans < n*m+1) {76 printf("%d\n", ans);77 }78 else {79 puts("-1");80 }81 82 }83 return 0;84 }

时间为60ms

后来参考别人的代码,可以利用尺取法解决这个问题

1 #include 
2 #include
3 #include
4 #include
5 #define MAX 102 6 7 int matrix[MAX][MAX]; 8 int tr[MAX]; 9 10 int merge(int n, int goal) {11 int ans = -1;12 int start = 0, end = 0, sum = 0;13 while (end < n) {14 if (sum < goal)15 sum += tr[end];16 while (sum >= goal) {17 int len = end - start + 1;18 if (ans == -1) ans = len;19 else if (len < ans) ans = len;20 sum -= tr[start++];21 }22 ++end;23 }24 return ans;25 }26 27 int main(int argc, char const *argv[])28 {29 int n, m, k;30 //freopen("input.txt","r",stdin);31 while(scanf("%d %d %d",&n, &m, &k) != EOF) {32 for(int i = 0; i < n; i++) {33 for(int j = 0; j < m; j++) {34 scanf("%d",&matrix[i][j]);35 }36 }37 38 int ans = n*m + 1;39 for(int i = 0; i < m; i++) {40 memset(tr,0,sizeof(tr));41 for(int j = i; j < m; j++) {42 //from i to j43 int ansij = -1;44 45 int base = j - i + 1;46 for(int h = 0; h < n; h++) {47 tr[h] = tr[h] + matrix[h][j]; 48 49 }50 /*for(int h = 0; h < n; h++) {51 printf("%d ",tr[h]);52 }53 puts("");*/54 ansij = merge(n, k);55 if(ansij != -1 && ansij *base < ans) {56 ans = ansij*base;57 }58 }59 }60 if(ans < n*m+1) {61 printf("%d\n", ans);62 }63 else {64 puts("-1");65 }66 67 }68 return 0;69 }

时间居然缩短到了10ms

转载于:https://www.cnblogs.com/jasonJie/p/5719771.html

你可能感兴趣的文章
[转]我国古代求解最大公约数的方法-更相减损术
查看>>
使用Keras编写GAN的入门
查看>>
数组排序 (选择排序、冒泡排序、插入排序、希尔排序)
查看>>
musql 单表查询
查看>>
【Git】标签管理
查看>>
[HNOI2017]大佬
查看>>
『重构--改善既有代码的设计』读书笔记----Hide Delegate
查看>>
1、libgdx简单介绍
查看>>
Swift iOS tableView static cell动态计算高度
查看>>
Windows Phone开发(24):启动器与选择器之发送短信 转:http://blog.csdn.net/tcjiaan/article/details/7404643...
查看>>
工厂模式(headfirst)笔记
查看>>
Hibernate初探之单表映射——创建持久化类
查看>>
File类
查看>>
有 n个人围成一圈,顺序排号。从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 问最后留下的是原来第几号的那位...
查看>>
mui框架通讯录检索
查看>>
正则表达式全集
查看>>
vuex中的dispatch和commit
查看>>
mybatis实战教程二:多对一关联查询(一对多)
查看>>
NodeMCU文档中文翻译 3 构建固件
查看>>
前端学习☞jquery
查看>>