hdu 4412 Sky Soldiers (区间dp 单调性)
2014-09-25 15:59
141 查看
Sky Soldiers
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 556 Accepted Submission(s): 179
[align=left]Problem Description[/align]
An airplane carried k soldiers with parachute is plan to let these soldiers jump off the plane along a straight air route. The landing point of these soldiers is undetermined because of various weather conditions. However, the statisticians
of the army can analysis the probability of landing in a certain place through landing history records. To make it simple, the statistician suggests that these sky soldiers will land on finite discrete points of a straight line.
This mission plans to place m provisions for the soldiers on the line for landing. These soldiers will be informed the direction of the nearest provision point by a special device after landing, and then walk to the point. The manager of this mission is asking
you for help: to determine m points for provisions so that the expected sum of walking distance should be minimized. You can put provisions on any point of the landing line.
[align=left]Input[/align]
There are multiple test cases. For each case, the first line contains two integers k and m (1 ≤ k ≤ 1,000, 1 ≤ m ≤ 50), which represent the number of sky soldiers and the number of positions to place provisions separately.
The following k lines contain descriptions of landing parameters for the soldiers numbered from 1 to k. Each description consists of an integer L followed by L pairs of (x, p), which indicates that the probability of the soldier's landing on integer coordination
x is p. It is guaranteed that all the p values are positive real numbers, and the sum of p in a single line is exactly 1. The same x may appear more than once on the same line which you should simply add up all the probability p of the pairs with equal x.
The number of places on which all the soldiers could land is no more than 1000 and it can not be less than m.
The input ends with k=m=0.
[align=left]Output[/align]
For each test case, output a line containing only one real number which indicates the minimum expected sum of distance these soldiers will move and should be rounded to two digits after the decimal point.
[align=left]Sample Input[/align]
2 1
2 0 0.5 1 0.5
2 1 0.1 3 0.9
0 0
[align=left]Sample Output[/align]
2.30
[align=left]Source[/align]
2012 ACM/ICPC Asia Regional Hangzhou Online
题意:
n个跳伞者,落地后,每个跳伞者可能会落在若干个点上,落在每个点都有一个概率(所有人都会落在x轴上)。现在在x轴上建立m个大本营,每个跳伞者走到最近的大本营。确定大本营建立的地点使得所有跳伞者所走的路程的期望最小。
思路:(来源于:点击打开链接)
联系到dp,dp[i][j]表示第i个大本营处理完前j个人的最小期望值,有dp[i][j]=dp[i-1][k]+cost[k+1][j]。那么主要的任务就是求cost[i][j]了,枚举起点,遍历结束点,同一个起点不同终点的中心点随着终点递增的,考虑中心点移一步会产生的影响,于是就能在O(n*n)处理出来了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 1005 #define MAXN 200005 #define INF 0x3f3f3f3f #define mod 1000000007 #define eps 1e-6 const double pi=acos(-1.0); typedef long long ll; using namespace std; int n,m,cnt; map<int,double>mp; map<int,double>::iterator it; double cost[maxn][maxn]; double dp[55][maxn],p[maxn]; int pos[maxn]; void init() { int i,j,cur; cnt=0; for(it=mp.begin();it!=mp.end();it++) { cnt++; pos[cnt]=it->first; p[cnt]=it->second; } double lp,rp,suml,sumr,best; for(i=1;i<=cnt;i++) { cost[i][i]=0; suml=sumr=rp=0; lp=p[i]; cur=i; for(j=i+1;j<=cnt;j++) { rp+=p[j]; sumr+=p[j]*(pos[j]-pos[cur]); best=suml+sumr; while(cur<cnt&&best>suml+sumr+(pos[cur+1]-pos[cur])*(lp-rp)) // 中心点右移 { suml+=(pos[cur+1]-pos[cur])*lp; sumr-=(pos[cur+1]-pos[cur])*rp; lp+=p[cur+1]; rp-=p[cur+1]; best=suml+sumr; cur++; } cost[i][j]=best; //printf("i:%d j:%d cur:%d best:%lf\n",i,j,cur,best); } } } void solve() { int i,j,k; double d,sum=p[1]; for(i=1;i<=m;i++) { for(j=1;j<=cnt;j++) { dp[i][j]=INF; } } for(j=1;j<=cnt;j++) { dp[1][j]=cost[1][j]; } double ans=INF; for(i=1;i<m;i++) { for(j=1;j<=cnt;j++) { for(k=j+1;k<=cnt;k++) { dp[i+1][k]=min(dp[i+1][k],dp[i][j]+cost[j+1][k]); } } ans=min(ans,dp[i][cnt]); } ans=min(ans,dp[m][cnt]); printf("%.2f\n",ans); } int main() { int i,j; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break ; mp.clear(); int num,x; double d; for(i=1;i<=n;i++) { scanf("%d",&num); for(j=1;j<=num;j++) { scanf("%d%lf",&x,&d); mp[x]+=d; } } init(); solve(); } return 0; } /* 2 1 2 0 0.5 1 0.5 2 1 0.1 3 0.9 0 0 */
相关文章推荐
- UVA1351-----String Compression-----区间DP(记忆化搜索实现)
- nyoj 括号匹配(二)(区间dp)
- 2017年浙江工业大学大学生程序设计迎新赛决赛—网络同步赛 G-取数游戏(区间dp)
- poj 3186 Treats for the Cows(区间dp)
- HDU 5273 Dylans loves sequence 区间DP
- Hdu 6212 Zuma【思维+区间Dp】
- HDU 4745 Two Rabbits【非连续最长回文子序列,区间DP】
- Hdu-6212 Zuma(区间DP)
- P1220 关路灯(区间dp)
- nyoj 737 石子合并(一)(区间DP)
- 区间dp专题
- LightOJ 1033 区间dp
- UVA 1626 - Brackets sequence 区间DP
- nyoj 15 括号匹配(二)(区间DP)
- Codeforces 509F Progress Monitoring (区间dp 或 记忆化搜索)
- 加分二叉树(感觉像是区间dp)
- 区间DP思维起步
- Codevs_P3304 水果姐逛水果街Ⅰ(线段树+区间DP)
- nyoj 1023 还是回文(区间DP)
- ZOJ - 3537 Cake 凸包+区间DP