• 【HDOJ】4412 Sky Soldiers


    1. 题目描述
    有$k$个伞兵跳伞,有$m$个汇点。当伞兵着陆后,需要走向离他最近的汇点。如何选择这$m$个结点,可以使得士兵最终行走的距离的期望最小。
    求这个最小的期望。

    2. 基本思路
    假设已经选好了这$m$个汇点,这也就确定了每个士兵的可能着陆点需要继续行走的距离。因此,这个期望为
    egin{align}
        E_{min} &= sum_{i=1}^{k} sum_{j=1}^{L_i} minDis(X_{ij}) * P_{ij}
    end{align}
    显然这等价于
    egin{align}
        xst &= set(X), nx = |xst|   \
        E_{min} &= sum_{i=1}^{nx} minDis(xst_i) * sum_{i=1}^{k} sum_{j=1}^{L_i} (X_{ij}==xst_i) * P{ij}  
    end{align}
    这也就意味着,最终的最小期望值与$k$大小无关,与$nx$大小有关,$sum_{i=1}^{k} sum_{j=1}^{L_i} (X_{ij}==xst_i) * P{ij} $其实是针对某个x的累加概率和。
    而$nx leq 1000$。因此,不妨设$dp[i][j]$表示当仅仅有i个汇点时,前j个x的最小期望值。显然有状态转移方程
    egin{align}
        dp[i][j] &= min (dp[i-1][k] + cost[k+1][j]), k in [1, j)
    end{align}
    关键就是求$cost[i][j]$,表示区间$[i,j]$内的最小费用(仅包含1个汇点)。
    而这显然是一个区间DP。有如下推导
    egin{align*}
        cost_k  &= sum_{i=1}^{k} (x_k-x_i) cdot P_i + sum_{i=k+1}^{n} (x_i-x_k) cdot P_i  \
        x_{k+1} &= x_k + Delta \
        cost_{k+1}  &= sum_{i=1}^{k+1} (x_{k+1}-x_i) cdot P_i + sum_{i=k+2}^{n} (x_i-x_{k+1}) cdot P_i   \
                &= sum_{i=1}^{k+1} (x_k+Delta-x_i) cdot P_i + sum_{i=k+2}^{n} (x_i-x_k-Delta) cdot P_i \
                &= sum_{i=1}^{k+1} (x_k-x_i) cdot P_i + sum_{i=k+2}^{n} (x_i-x_k) cdot P_i + Delta (sum_{i=1}^{k+1}P_i - sum_{i=k+2}^{n}P_i) \
                &= sum_{i=1}^{k} (x_k-x_i) cdot P_i + sum_{i=k+1}^{n} (x_i-x_k) cdot P_i - 2Delta cdot P_{k+1} + Delta (sum_{i=1}^{k+1}P_i - sum_{i=k+2}^{n}P_i) \
                &= cost_k + Delta (sum_{i=1}^{k}P_i + P_{k+1} - sum_{i=k+1}^{n}P_i + P_{k+1} - 2P_{k+1}) \
                &= cost_k + Delta (sum_{i=1}^{k}P_i - sum_{i=k+1}^{n}P_i)
    end{align*}
    这让我在已知$x_k$为$[1,n]$的汇点时,可以快速求出当$x_{k+1}$为汇点时的费用值。$Delta > 0$恒成立,而$sum_{i=1}^{k}P_i - sum_{i=k+1}^{n}P_i$也是单调递增的,因此求最优的$x_k$时可以使用单调性优化。

    3. 代码

      1 /* 4412 */
      2 #include <iostream>
      3 #include <sstream>
      4 #include <string>
      5 #include <map>
      6 #include <queue>
      7 #include <set>
      8 #include <stack>
      9 #include <vector>
     10 #include <deque>
     11 #include <bitset>
     12 #include <algorithm>
     13 #include <cstdio>
     14 #include <cmath>
     15 #include <ctime>
     16 #include <cstring>
     17 #include <climits>
     18 #include <cctype>
     19 #include <cassert>
     20 #include <functional>
     21 #include <iterator>
     22 #include <iomanip>
     23 using namespace std;
     24 //#pragma comment(linker,"/STACK:102400000,1024000")
     25 
     26 #define sti                set<int>
     27 #define stpii            set<pair<int, int> >
     28 #define mpii            map<int,int>
     29 #define vi                vector<int>
     30 #define pii                pair<int,int>
     31 #define vpii            vector<pair<int,int> >
     32 #define rep(i, a, n)     for (int i=a;i<n;++i)
     33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
     34 #define clr                clear
     35 #define pb                 push_back
     36 #define mp                 make_pair
     37 #define fir                first
     38 #define sec                second
     39 #define all(x)             (x).begin(),(x).end()
     40 #define SZ(x)             ((int)(x).size())
     41 #define lson            l, mid, rt<<1
     42 #define rson            mid+1, r, rt<<1|1
     43 
     44 typedef struct node_t {
     45     int x;
     46     double p;
     47     
     48     node_t() {}
     49     node_t(int x, double p):
     50         x(x), p(p) {}
     51         
     52     friend bool operator< (const node_t& a, const node_t& b) {
     53         return a.x < b.x;
     54     }
     55     
     56 } node_t;
     57 
     58 const double INF = 1e18;
     59 const int maxn = 1005;
     60 const int maxm = 55;
     61 double cost[maxn][maxn];
     62 double dp[maxm][maxn];
     63 map<int,double> tb;
     64 map<int,double>::iterator iter;
     65 node_t nd[maxn];
     66 int n, m;
     67 
     68 void init_Cost(int n) {
     69     double mn, tmp;
     70     
     71     rep(i, 0, n) {
     72         int k = i;
     73         double pl = nd[i].p, pr = 0.0;
     74         
     75         mn = 0.0;
     76         cost[i][i] = 0;
     77         
     78         rep(j, i+1, n) {
     79             pr += nd[j].p;
     80             mn += (nd[j].x - nd[k].x) * nd[j].p;
     81             while (k<j && mn > mn + (nd[k+1].x-nd[k].x) * (pl - pr)) {
     82                 mn += (nd[k+1].x-nd[k].x) * (pl - pr);
     83                 ++k;
     84                 pl += nd[k].p;
     85                 pr -= nd[k].p;
     86             }
     87             cost[i][j] = mn;
     88         }
     89     }
     90 }
     91 
     92 void solve() {
     93     int pn = 0;
     94     
     95     for (iter=tb.begin(); iter!=tb.end(); ++iter) {
     96         nd[pn].x = iter->fir;
     97         nd[pn].p = iter->sec;
     98         ++pn;
     99     }
    100     
    101     sort(nd, nd+pn);
    102     
    103     init_Cost(pn);
    104     
    105     rep(j, 0, pn)
    106         dp[0][j] = cost[0][j];
    107         
    108     rep(i, 1, m) {
    109         rep(j, 0, pn) {
    110             dp[i][j] = dp[i-1][j];
    111             rep(k, 0, j)
    112                 dp[i][j] = min(dp[i][j], dp[i-1][k]+cost[k+1][j]);
    113         }
    114     }
    115     
    116     double ans = INF;
    117     ans = min(ans, dp[m-1][pn-1]);
    118     printf("%.2lf
    ", ans);
    119 }
    120 
    121 int main() {
    122     ios::sync_with_stdio(false);
    123     #ifndef ONLINE_JUDGE
    124         freopen("data.in", "r", stdin);
    125         freopen("data.out", "w", stdout);
    126     #endif
    127     
    128     int l;
    129     int x;
    130     double p;
    131     
    132     while (scanf("%d %d", &n, &m)!=EOF && (n||m)) {
    133         tb.clr();
    134         rep(i, 0, n) {
    135             scanf("%d", &l);
    136             rep(j, 0, l) {
    137                 scanf("%d%lf", &x, &p);
    138                 tb[x] += p;
    139             }
    140         }
    141         solve();
    142     }
    143     
    144     #ifndef ONLINE_JUDGE
    145         printf("time = %d.
    ", (int)clock());
    146     #endif
    147     
    148     return 0;
    149 }
  • 相关阅读:
    docker中 启动所有的容器命令
    使用Docker部署服务
    docker常规操作——启动、停止、重启容器实例
    Docker Swarm 常用命令
    ArcGIS中search窗口不能查询解决办法
    ylpy
    第7章
    ArcGIS 将模型导出为 Python 脚本
    11章代码
    9章代码
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5247311.html
Copyright © 2020-2023  润新知