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 ", res); 34 } 35 }
B:(hdu1060)
题意:
N^N的最左边一位数字
解决:
A = lg(nn) = n * lg(n)
则 10A = nn, 设p 为 A 的小数部分,则10p 的整数部分就是答案
C:(hdu1007)
题意:
平面最近点对
解决:
分治。
复杂度:O(n*log(n))
1 #include <bits/stdc++.h> 2 3 const int MAXN = 1e5+10; 4 5 struct Point{ 6 double x, y; 7 bool operator < (const Point &tmp) const 8 { 9 return x < tmp.x; 10 } 11 }point[MAXN], t[MAXN]; 12 bool cmp(Point a, Point b) 13 { 14 return a.y < b.y; 15 } 16 int n; 17 18 double getDist(Point &a, Point &b) 19 { 20 return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ); 21 } 22 23 double fuck(int l, int r) 24 { 25 if (l == r) 26 return 1e14; 27 if (r - l == 1) 28 return getDist(point[l], point[r]); 29 int mid = l + r >> 1; 30 double d = std::min(fuck(l, mid), fuck(mid, r)); 31 int cnt = 0; 32 for (int i = mid-1; i >= l; --i) 33 if (point[mid].x - point[i].x < d) 34 t[++cnt] = point[i]; 35 for (int i = mid+1; i <= r; ++i) 36 if (point[i].x - point[mid].x < d) 37 t[++cnt] = point[i]; 38 std::sort(t+1, t+cnt+1, cmp); 39 for (int i = 1; i <= cnt; ++i) { 40 for (int j = i+1; j <= cnt; ++j) { 41 if (t[j].y - t[i].y < d) 42 d = std::min(d, getDist(t[j], t[i])); 43 else 44 break; 45 } 46 } 47 return d; 48 } 49 50 int main() 51 { 52 while (~scanf("%d", &n), n) { 53 for (int i = 1; i <= n; ++i) 54 scanf("%lf%lf", &point[i].x, &point[i].y); 55 std::sort(point+1, point+n+1); 56 printf("%.2f ", fuck(1, n)/2); 57 } 58 }
D:(hdu4007)
题意:
给定n个点,求边长为R的正方形最多可以框住多少点(可以在边框上)
解决:
解法一:可以用扫描线,对每个点,以这个点为左下角点构造出一个矩形,则一共有1000个矩形,求个矩形面积交,线段树维护区间最大值即可。
解法二:先对所有点按照横坐标排序,从左到右枚举点,作为矩形左边框的横坐标,二分出矩形框能框住的最右边的点。这些点的横坐标差值最大不超过R,将这些点的纵坐标放在一个数组里面,排序之后尺取法扫一遍。
二者复杂度均为:O(n*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 ", 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];