题目1102:最小面积子矩阵

题目1102:最小面积子矩阵

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:510

解决:113

题目描述:

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

输入:

每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K
接下来N行,每行M个数,表示矩阵每个元素的值

输出:

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

样例输入:
4 4 10
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
样例输出:
1
来源:
2010年上海交通大学计算机研究生机试真题
答疑:
解题遇到问题?分享解题心得?讨论本题请访问: http://t.jobdu.com/thread-7825-1-1.html



#include <stdio.h> const int size = 110; int mat[size][size]; int sum[size][size]; int tok[size]; int n, m, k; bool check(int len) { for (int i = 1; i + len - 1 <= m; i ++) if (tok[i + len - 1] - tok[i - 1] >= k) return true; return false; } int main() { int a; while (scanf("%d %d %d", &n, &m, &k) != EOF) { for (int i = 1; i <= m; i ++) sum[0][i] = 0; for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) { scanf("%d", &mat[i][j]); sum[i][j] = sum[i-1][j] + mat[i][j]; } int ans = -1; for (int len = 1; len <= n; len ++) for (int i = 1; i + len - 1 <= n; i ++) { tok[0] = 0; for (int j = 1; j <= m; j ++) { tok[j] = sum[i + len - 1][j] - sum[i - 1][j]; tok[j] += tok[j-1]; } if (tok[m] < k) continue; // printf("len = %d, %d!!\n", len, tok[m]); //枚举len,二分mid int lf = 1, rt = m + 1; int mid; while (lf < rt) { mid = (lf + rt) >> 1; // printf("....(%d, %d)\n", lf, rt); if (ans != -1 && mid * len > ans) { rt = mid; continue; } if (check(mid)) { if (ans == -1 || ans > mid * len) ans = mid * len; rt = mid; //printf("ans = %d\n", ans); } else lf = mid + 1; } } printf("%d\n", ans); } return 0; } /* 1 5 10 1 2 5 3 7 */ /************************************************************** Problem: 1102 User: scode Language: C++ Result: Accepted Time:10 ms Memory:1108 kb **************************

我的 超时

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstring>
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)<(b)?(b):(a))
int a[101][101];
int main()
{
//freopen("in.txt","r",stdin);
int n,m,k,i,j,p,q,temp,min,size1,size2,sum,res; bool flag;
while (scanf("%d %d %d", &n,&m,&k)!=EOF)
{
memset(a,0,sizeof(a));flag=false;res=100000;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(size1=1;size1<=n;size1++)//size
{
for(size2=1;size2<=m;size2++)
{
//if(flag==true) break;

for(i=1;i<=n-size1+1;i++)
{
for(j=1;j<=m-size2+1;j++)
{
sum=0;
for(p=0;p<size1;p++)
for(q=0;q<size2;q++)
sum+=a[i+p][j+q];
if( sum>=k ) { flag=true; if(res>size1*size2) res=size1*size2; }

 
  


//if(size1==3&&size2==1) printf("in&&&i %d j %d size1 %dsize2 %d sum %d\n",i,j,size1,size2,sum);
}
//if(size1==3&&size2==1) printf("i %d j %d size1 %d size2 %d sum %d\n",i,j,size1,size2,sum);
}
}
}
if(flag) printf("%d\n",res);
else printf("-1\n");

}

return 0;
}

 





2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 105
using namespace std;
 
int N, M, K, G[MAXN][MAXN], S[MAXN*MAXN], lim;
int rec[MAXN*MAXN], idx, sum[MAXN][MAXN];
 
struct Node
{
     int x, y;
}que[MAXN];
 
int front, tail;
 
inline void pre()
{
     int k;
     lim = N*M;
     memset (S, 0, sizeof (S));
     idx = -1;
     // getstatus
     for ( int i = 1; i <= N; ++i) {
         k = min(M, lim / i); // 选取相对小的值,排除不合法情况
         for ( int j = 1; j <= k; ++j) {
             S[i*j] = 1;
         }
     }
     for ( int i = 1; i <= lim; ++i) {
         if (S[i]) {
             rec[++idx] = i;
         }
     }
     // getsum
     for ( int i = 1; i <= N; ++i) {
         for ( int j = 1; j <= M; ++j) {
             sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + G[i][j];
         }
     }
}
 
bool judge()
{
     int xx, yy, zz, lx, ly;
     for ( int k = 1; k <= tail; ++k) {
         lx = N - que[k].x + 1, ly = M - que[k].y + 1;
         for ( int i = 1; i <= lx; ++i) {
             for ( int j = 1; j <= ly; ++j) {
                 xx = i+que[k].x-1, yy = j+que[k].y-1;
                 if (xx <= N && yy <= M) {
                     zz = sum[xx][yy] - sum[i-1][yy] - sum[xx][j-1] + sum[i-1][j-1];
                     if (zz >= K) return true ;
                 }
             }
         }
     }
     return false ;
}
 
bool Ac( int x) // 能够保证所有的x都是合法值
{
     front = tail = 0;
     for ( int i = 1; i <= N; ++i) {
         if (x % i == 0) {
             ++tail;
             que[tail].x = i, que[tail].y = x / i;
         }
     } // 处理处当前面积的分解情况
     if (judge()) {
         return true ;
     }
     return false ;
}
 
int bsearch ( int l, int r)
{
     int mid, ret = -1;
     while (l <= r) {
         mid = (l + r) >> 1;
         if (Ac(rec[mid])) {
             ret = rec[mid];
             r = mid - 1;
         }
         else {
             l = mid + 1;   
         }
     }
     return ret;
}
 
int force()
{
     for ( int i = 0; i <= idx; ++i) {
         if (Ac(rec[i])) {
             return rec[i];
         }   
     }
     return -1;
}
 
int main()
{
     while ( scanf ( "%d %d %d" , &N, &M, &K) != EOF) {
         for ( int i = 1; i <= N; ++i) {
             for ( int j = 1; j <= M; ++j) {
                 scanf ( "%d" , &G[i][j]);
             }
         }
         pre();
     //    printf("%d\n", bsearch(0, idx));
         printf ( "%d\n" , force());
     }
     return 0;   
}
/**************************************************************
     Problem: 1102
     User: huashiyiqike
     Language: C++
     Result: Accepted
     Time:40 ms
     Memory:1184 kb
 

 

转载于:https://www.cnblogs.com/huashiyiqike/articles/2890481.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值