A:(hdu1081)
题意:
求和最大的子矩阵
解决:
先考虑一维数组,可以O(n)复杂度求出 和值最大的连续子序列。
同理,对每一行维护前缀和,然后枚举从 l 列到 r 列,每行的 l 列到 r 列可以通过前缀和O(1)求出,然后对每行的 l 列和r 列之间的和值作为一维数组的元素,O(n)求出答案。
总复杂度 :O(n3)
1 #include <bits/stdc++.h> 2 3 const int MAXN = 133; 4 5 int n; 6 int ma[MAXN][MAXN]; 7 8 int main() 9 { 10 while (~scanf("%d", &n)) { 11 for (int i = 1; i <= n; ++i) { 12 ma[i][0] = 0; 13 for (int j = 1; j <= n; ++j) { 14 scanf("%d", &ma[i][j]); 15 ma[i][j] += ma[i][j-1]; 16 } 17 } 18 int res = -0x7fffffff; 19 for (int l = 1; l <= n; ++l) { 20 for (int r = l; r <= n; ++r) { 21 int tmp = 0, ans = -0x7fffffff; 22 for (int i = 1; i <= n; ++i) { 23 int ele = ma[i][r] - ma[i][l-1]; 24 tmp += ele; 25 ans = std::max(ans, tmp); 26 if (tmp < 0) { 27 tmp = 0; 28 } 29 } 30 res = std::max(res, ans); 31 } 32 } 33 printf("%d\n", res); 34 } 35 }
B:(hdu1060)
题意:
N^N的最左边一位数字
解决:
A = lg(nn) = n * lg(n)
则 10A = nn, 设p 为 A 的小数部分,则10p 的整数部分就是答案
C:(hdu1007)
题意:
平面最近点对
解决:
这个题目比较取巧,解法很多。
可以用旋转卡壳,可以分治,也可以两次排序直接求
有一点很重要的思想,如果两个点是平面最近点,则以这两个点为对角线的矩形中一定没有其他点。根据这个思想可以排序两次,用相邻点的距离维护最小值。
复杂度:O(n*log(n))
D:(hdu4007)
题意:
给定n个点,求边长为R的正方形最多可以框住多少点(可以在边框上)
解决:
解法一:可以用扫描线,对每个点,以这个点为左下角点构造出一个矩形,则一共有1000个矩形,求个矩形面积交,线段树维护区间最大值即可。
解法二:先对所有点按照横坐标排序,从左到右枚举点,作为矩形左边框的横坐标,二分出矩形框能框住的最右边的点。这些点的横坐标差值最大不超过R,将这些点的纵坐标放在一个数组里面,排序之后尺取法扫一遍。
二者复杂度均为:O(n*log(n))
1 #include <bits/stdc++.h> 2 3 struct Point{ 4 int x, y; 5 bool operator < (const Point &tmp) const 6 { 7 return x < tmp.x; 8 } 9 }point[1000+10]; 10 11 12 13 int n, R; 14 int t[1000+10]; 15 16 int check(int l, int r) 17 { 18 int cnt = 0; 19 for (int i = l; i <= r; ++i) 20 t[++cnt] = point[i].y; 21 std::sort(t+1, t+1+cnt); 22 int i = 1, j = 1; 23 int res = 0; 24 int tmp = 0; 25 while (j <= cnt) { 26 if (t[j] - t[i] <= R) { 27 ++j; 28 ++tmp; 29 } 30 else { 31 ++i; 32 --tmp; 33 } 34 res = std::max(res, tmp); 35 } 36 return res; 37 } 38 39 int main() 40 { 41 while (~scanf("%d%d", &n, &R)) { 42 for (int i = 1; i <= n; ++i) 43 scanf("%d%d", &point[i].x, &point[i].y); 44 std::sort(point+1, point+1+n); 45 int res = 0; 46 for (int i = 1; i <= n; ++i) { 47 int l = i, r = n; 48 while (l <= r) { 49 int mid = l + r >> 1; 50 if (point[mid].x > point[i].x + R) 51 r = mid - 1; 52 else 53 l = mid + 1; 54 } 55 res = std::max(res, check(i ,l-1)); 56 } 57 printf("%d\n", res); 58 } 59 }
E:(hdu1176)
题意:
天上会有n个馅饼掉下来,分别是在t时刻,x位置(0 <= x <= 10),人一开始在5位置,每时刻可以左移或者右移一个单位,求能接到馅饼最大值
解决:
cake[t][x]为在t时刻x位置会有多少馅饼掉下来。
dp[t][x] = max(dp[t-1][x-1], dp[t-1][x], dp[t+1][x]) + cake[t][x];