TakeoffYoung

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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 }
View Code

 

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\n", fuck(1, n)/2);
57     }
58 }
View Code

 

 

 

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\n", res);
58     }
59 }
View Code

 

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];

 

posted on 2015-11-03 22:14  TakeoffYoung  阅读(159)  评论(0编辑  收藏  举报