zoukankan      html  css  js  c++  java
  • 2015-11-3-Training(for 2014th)

    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 }
    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
    ", 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
    ", 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];

  • 相关阅读:
    SpringBoot04-web
    springboot03-日志功能
    SpringBoot02-自动配置原理
    SpringBoot02
    SpringBoot01
    八大排序算法
    SpringSecurity04
    SpringSecurity03
    SpringSecurity02
    SpringSecurity01
  • 原文地址:https://www.cnblogs.com/takeoffyoung/p/4934559.html
Copyright © 2011-2022 走看看