网易2017校园招聘数据挖掘笔试题编程题 分田地
2016-08-04 10:15
609 查看
题目:
牛牛和15个朋友玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成16份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地,作为牛牛最好的朋友,你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?输入描述
每个输入包含1个测试用例。每个测试用例的第一行包含两个整数n和m(1 <= n,m <= 75),表示田地的大小,接下来的n行,每行包含m个0-9之间的数字,表示每块位置的价值。输出描述
输出一行表示牛牛所能取得的最大的价值。输入例子
4 43332
3233
3332
2323
输出例子
2思路
“最小值最大问题”,先二分试试。枚举横向的三刀,纵向上在二分答案后贪心地靠左切,使得每个区域刚好全部大于等于答案,根据能否切满三刀来确定答案区间。这个时间复杂度算一下是O(n3mlogx)的,其中x是最大可能答案。
对于题目中给的数据,这样的复杂度表示鸭梨山大(codeforces.com除外),得考虑一下如何优化。
依然枚举横向的三刀,现在问题是如何确定这三刀,使得16个区域最小值最大。不妨先切中间那刀,那么问题变为如何切左边那刀和右边那刀,很显然这两个问题相互独立。用f[i]表示前i列的最优切法所得到的值,g[i]表示i~m列的最优切法得到的值,那么答案=max(min(f[i],g[i+1])),1<=i<m。容易证明f[i]和g[i]的最优决策都是单调的,于是它们都可以在O(m)的时间内算出来,因此最后复杂度变为O(n3m)。
参考程序一(枚举+二分):
#include <bits/stdc++.h> using namespace std; int n, m, a[100][100], sum[100][100], l, r, M; int getsum(int x1, int y1, int x2, int y2) { return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1]; } bool ok(int val, int ix, int jx, int kx, int y1, int y2) { int v1 = getsum(1, y1, ix, y2); int v2 = getsum(ix + 1, y1, jx, y2); int v3 = getsum(jx + 1, y1, kx, y2); int v4 = getsum(kx + 1, y1, n, y2); return v1 >= val && v2 >= val && v3 >= val && v4 >= val; } bool chk(int x) { int c, y1; for (int i = 1; i < n; i++) { for (int j = i + 1; j < n; j++) { for (int k = j + 1; k < n; k++) { c = 0; y1 = 1; for (int y2 = 1; y2 <= m && c < 4; y2++) { if (ok(x, i, j, k, y1, y2)) { c++; y1 = y2 + 1; } } if (c == 4) return true; } } } return false; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; } } 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] + a[i][j]; } } l = 0; r = 1e6; while (l < r) { M = l + r + 1 >> 1; if (chk(M)) l = M; else r = M - 1; } cout << l << endl; return 0; }
参考程序二(枚举+dp):
#include <bits/stdc++.h> using namespace std; int f[100], ix, jx, kx, n, m, a[100][100], sum[100][100], ans; int min(int a, int b) { if (a < b) return a; return b; } int getsum(int x1, int y1, int x2, int y2) { return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1]; } int getval1(int p, int r) { int v1 = min(getsum(1, 1, ix, p), getsum(1, p + 1, ix, r)); int v2 = min(getsum(ix + 1, 1, jx, p), getsum(ix + 1, p + 1, jx, r)); int v3 = min(getsum(jx + 1, 1, kx, p), getsum(jx + 1, p + 1, kx, r)); int v4 = min(getsum(kx + 1, 1, n, p), getsum(kx + 1, p + 1, n, r)); return min(min(v1, v2), min(v3, v4)); } int getval2(int p, int l) { int v1 = min(getsum(1, p, ix, m), getsum(1, l, ix, p - 1)); int v2 = min(getsum(ix + 1, p, jx, m), getsum(ix + 1, l, jx, p - 1)); int v3 = min(getsum(jx + 1, p, kx, m), getsum(jx + 1, l, kx, p - 1)); int v4 = min(getsum(kx + 1, p, n, m), getsum(kx + 1, l, n, p - 1)); return min(min(v1, v2), min(v3, v4)); } int calc() { int j = 1, ans, buf, val; f[1] = 0; for (int i = 2; i <= m; i++) { val = getval1(j, i); while (j + 1 < i && (buf = getval1(j + 1, i)) >= val) { j++; val = buf; } f[i] = val; } ans = 0; j = m; for (int i = m - 1; i >= 2; i--) { val = getval2(j, i); while (j - 1 > i && (buf = getval2(j - 1, i)) >= val) { j--; val = buf; } ans = max(ans, min(f[i - 1], val)); } return ans; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; } } 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] + a[i][j]; } } ans = 0; for (ix = 1; ix < n; ix++) { for (jx = ix + 1; jx < n; jx++) { for (kx = jx + 1; kx < n; kx++) { ans = max(ans, calc()); } } } cout << ans << endl; return 0; }
相关文章推荐
- 网易2017校园招聘数据挖掘笔试题
- 网易2017校园招聘数据挖掘笔试题
- 2017网易实习数据挖掘工程师笔试在线编程题《分饼干》
- 网易2017校园招聘笔试程序题(分田地)
- 【算法】网易2017校园招聘笔试程序题(分田地)
- 网易校园招聘2017编程题--回文数问题
- 网易2017校园招聘笔试题 跳石板
- 网易2017校园招聘笔试题 最大的奇约数
- 网易2017校园招聘笔试题 优雅的点
- 京东2017校园招聘数据与算法方向笔试题
- 网易2017校园招聘笔试题:计算糖果
- 网易2017校园招聘笔试题:优雅的点
- 奇虎360_2017校园招聘笔试编程题第一题
- 网易2017校园招聘编程题——暗黑字符串
- 2015年校园招聘之腾讯(数据挖掘)笔试面试题目
- 网易2017校园招聘笔试题:计算糖果
- 网易2017校园招聘笔试题 数字翻转
- 2017校园招聘腾讯笔试题 在线编程题
- 网易2017校园招聘笔试题:数字翻转
- 网易2017校园招聘笔试题:回文序列