• Google题解


    Kickstart2017 RoundB

    B.题意: 二维平面上有n个点, 每个点坐标(xi, yi), 权值wi, 问: 在平面上找一点p, 使得 Σwi*max(|X-xi|, |Y-yi|)最小, (X, Y)为p点坐标。求该最小值。

    二维空间:

    欧几里得距离:d=√(|x1-x2|2+|y1-y2|2)

    曼哈顿距离 :d=|x1-x2|+|y1-y2|,到某点的曼哈顿距离为r的点组成一个边长为√2*r的正方形,且边与坐标轴成45度

    切比雪夫距离:d=max(|x1-x2|,|y1-y2|),到某点的切比雪夫距离为r的点组成一个边长为2*r的正方形,且边与坐标轴平行

      1 /*
      2 题解: 赛后看到有不少随机化算法可乱搞过去
      3 该题是二维平面邮局距离(参见《算法导论》)的变形
      4 
      5 simple版:一维下, 使得Σwi*|X-xi|最小, 其中所有wi = 1. 答案显然为xi的中位数
      6 middle版:我们可以将wi看成有wi个点重合, 权值均为1, 则可套用simple版解法
      7 hard版:二维下, 使得 Σwi*(|X-xi| +|Y-yi|)最小. X轴, Y轴分开解即可
      8 此题:我们将整个平面旋转45°即可变为hard版. 为什么?
      9 
     10 因为hard中|X-xi| +|Y-yi|表示的边界形状为以(xi, yi)为中心的45°倾斜的正方形
     11 而本题max(|X-xi|, |Y-yi|)表示的边界形状为以(xi, yi)为中心的正方形
     12 */
     13 
     14 #include <iostream>
     15 #include <algorithm>
     16 #include <vector>
     17 #include <string>
     18 #include <unordered_set>
     19 #include <unordered_map>
     20 #include <set>
     21 #include <map>
     22 #include <queue>
     23 #include <stack>
     24 #include <functional>
     25 #include <cmath>
     26 #include <string.h>
     27 
     28 using namespace std;
     29 using ull = unsigned long long;
     30 using ll = long long;
     31 using db = double;
     32 using PII = pair<int, int>;
     33 
     34 template<typename T>
     35 void print_vec(T& container, const std::string& sep = " "){
     36     for (auto& x: container){
     37         std::cout << x << sep;
     38     }
     39     std::cout << std::endl;
     40 }
     41 
     42 template<typename T>
     43 void print_map(T& mp){
     44     for(auto& x: mp){
     45         std::cout << x.first << " " << x.second << std::endl;
     46     }
     47 }
     48 
     49 struct Point{
     50     double x, y, w;
     51     void input(){
     52         cin >> x >> y >> w;
     53     }
     54     double dist(double _x, double _y){
     55         return fabs(x - _x) + fabs(y - _y);
     56     }
     57     void rotate(){
     58         static double ang = 45.0 / 180 * acos(-1.0);
     59         double x1 = x * cos(ang) - y * sin(ang);
     60         double y1 = x * sin(ang) + y * cos(ang);
     61         x = x1 * sin(ang) ;
     62         y = y1 * sin(ang) ;
     63     }
     64 };
     65 struct Problem{
     66 
     67     int N;
     68     Point p[10010];
     69     void read(){
     70         cin >> N;
     71         for (int i = 0; i < N; i++){
     72             p[i].input();
     73             p[i].rotate();
     74         }
     75     }
     76 
     77     struct WEIGHT{
     78         double w;
     79         double x;
     80         bool operator<(const WEIGHT& wt) const{
     81             return x < wt.x;
     82         }
     83     };
     84 
     85     double calc(WEIGHT wt[], int n){
     86         sort(wt, wt + n);
     87         double ans = 0;
     88         double cur_x = wt[0].x;
     89         double pre_sum = 0;
     90         double suf_sum = 0;
     91         for (int i = 0; i < n; i++){
     92             ans += (wt[i].x - cur_x) * wt[i].w;
     93             suf_sum += wt[i].w; 
     94         }
     95         double ret = ans;
     96         for (int i = 1; i < n; i++){
     97             double nxt_x = wt[i].x;
     98             suf_sum -= wt[i-1].w;
     99             pre_sum += wt[i-1].w;
    100             ans -= suf_sum * (nxt_x - cur_x);
    101             ans += pre_sum * (nxt_x - cur_x);
    102             cur_x = nxt_x;
    103             ret = min(ans, ret);
    104         }
    105         return ret;
    106     }
    107     void solve(int ca){
    108         printf("Case #%d: ", ca);
    109         
    110         WEIGHT vx[10010], vy[10010];
    111         for (int i = 0; i < N; i++){
    112             vx[i].x = p[i].x;
    113             vx[i].w = p[i].w;
    114             vy[i].x = p[i].y;
    115             vy[i].w = p[i].w;
    116         }
    117         double sum = calc(vx, N) + calc(vy, N);
    118         printf("%.7f
    ", sum);
    119     }
    120 };
    121 
    122 int main(){
    123     int T;
    124     cin >> T;
    125     for (int ca = 1; ca <= T; ca++){
    126         Problem p;
    127         p.read();
    128         p.solve(ca);
    129     }
    130 }
    View Code

     附随机化模拟退火算法:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <vector>
     6 #include <map>
     7 #include <set>
     8 #include <climits>
     9 #include <stack>
    10 #include <queue>
    11 #include <ctime>
    12 #include <string>
    13 #include <iostream>
    14 #include <algorithm>
    15 using namespace std;
    16 
    17 #define MEM(a,b) memset(a,b,sizeof(a))
    18 #define REP(i,n) for(int i=0;i<(n);++i)
    19 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
    21 #define MP(a,b) make_pair(a,b)
    22 
    23 typedef long long ll;
    24 typedef pair<int,int> pii;
    25 const int INF = (1 << 30) - 1;
    26 const int MAXN = 10010;
    27 const double cof = 0.5;
    28 const double eps = 1e-3;
    29 const double deta = 0.7;
    30 
    31 int T,N;
    32 double X[MAXN],Y[MAXN], W[MAXN];
    33 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
    34 
    35 double Dis(double a1,double b1,double a2,double b2){
    36     return max(abs(a1-a2), abs(b1-b2));
    37 }
    38 
    39 double Cal(double a,double b){
    40     double res = Dis(a,b,X[0],Y[0]) * W[0];
    41     FOR(i,1,N - 1) res += Dis(a,b,X[i],Y[i]) * W[i];
    42     return res;
    43 }
    44 
    45 int main(){
    46     srand((unsigned)time(NULL));
    47     int a,b;
    48     scanf("%d",&T);
    49     FOR(tt,1,T){
    50         scanf("%d",&N);
    51         REP(i,N) scanf("%lf%lf%lf",&X[i],&Y[i], &W[i]);
    52         double ans = -1,ansx,ansy;
    53         REP(o,100){
    54             double sx = rand() % (N + 1);
    55             double sy = rand() % (N + 1);
    56             double res = Cal(sx,sy);
    57             double step = N;
    58             while(step > eps){
    59                 while(1){
    60                     bool mov = false;
    61                     REP(k,4){
    62                         double tx = sx + dir[k][0] * step;
    63                         double ty = sy + dir[k][1] * step;
    64                         if(tx < -10000 || tx > 10000 || ty < -10000 || ty > 10000) continue;
    65                         double tmp = Cal(tx,ty);
    66                         if(tmp < res || (double)rand()/INT_MAX > deta){
    67                             res = tmp;
    68                             sx = tx;
    69                             sy = ty;
    70                             mov = true;
    71                         }
    72                     }
    73                     if(mov == false) break;
    74                 }
    75                 step *= cof;
    76             }
    77             if(ans == -1 || res < ans){
    78                 ans = res;
    79                 ansx = sx;
    80                 ansy = sy;
    81             }
    82         }
    83         printf("Case #%d: %.6lf
    ", tt, ans);
    84         //printf("The safest point is (%.1f, %.1f).
    ",ansx,ansy);
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    mongodb的账户管理
    mongo备份与恢复
    mongo索引
    聚合aggregate
    07-【jsp基本了解】
    Servlet登录小案例
    06-【servletconfig、servletContext 】
    05-【session、cookie】
    jQuery
    04-【servlet转发和重定向】
  • 原文地址:https://www.cnblogs.com/dirge/p/6821849.html
Copyright © 2020-2023  润新知