HDU-4605 Magic Ball Game

题意:给定一颗以1为根的数,每个节点要么有两个孩子节点,要么没有孩子,每个节点有一个重量,现在从节点1往下放置一个小球,根据小球和节点的重量的不同球落下的轨迹是一个概率问题:

设球的重量为X,节点的重量为w[i]:
X = w[i],那么小球的运动将停止;
X < w[i],那么小球向左孩子下落的概率为1/2,向右孩子下落的概率为1/2;
X > w[i],那么小球向左落下概率为1/8,向右落下的概率为7/8。

现在有Q组询问,问小球的质量为X,落到v节点的概率为多大?

分析:最直接的办法就是直接暴力求解该题,从询问的叶子节点开始向上寻找,进行概率的累加,比赛的时候这样写,超时了。赛后听说是使用的树状数组维护路径状态进行求解。具体过程是在一个dfs的过程中,统计好当前位置的左路径的节点和右路径的节点,然后将小球的质量在树状数组中进行查找,计算出比小球质量较小的节点数以及比小球质量较大的节点数,累加概率即可。注意直接dfs会爆栈,使用编译器命令后解决该问题。

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; struct Node {
int num, vertex, weight, ansx, ansy;
Node(int _n, int _v, int _w, int _ansx, int _ansy) : \
num(_n), vertex(_v), weight(_w), ansx(_ansx), ansy(_ansy) {}
bool operator < (const Node &other) const {
return num < other.num;
}
}; const int N = ;
vector<Node>v[N], vv;
// first元素是询问的编号,pair的第一个元素是询问的
int ch[N][], w[N];
int n, m;
int num[N<<], cnt;
map<int,int>mp;
int lbit[N<<], rbit[N<<]; // 因为询问和给定节点加起来上限是2*N个不同的数值 inline int lowbit(int x) {
return x & -x;
} void add(int bit[], int x, int val) {
for (int i = x; i <= cnt; i += lowbit(i)) {
bit[i] += val;
}
} int sum(int bit[], int x) {
int ret = ;
for (int i = x; i > ; i -= lowbit(i)) {
ret += bit[i];
}
return ret;
} void dfs(int u) {
for (int i = ; i < (int)v[u].size(); ++i) {
int weight = mp[v[u][i].weight];
int lsum = sum(lbit, weight), rsum = sum(rbit, weight);
int ltot = sum(lbit, cnt), rtot = sum(rbit, cnt);
bool find = lsum && bool(lsum - sum(lbit, weight-)) || rsum && bool(rsum - sum(rbit, weight-));
if (!find) {
v[u][i].ansx = rsum;
v[u][i].ansy = rtot-rsum + ltot-lsum + lsum* + rsum*;
} else {
v[u][i].ansx = v[u][i].ansy = -;
}
}
if (ch[u][]) {
add(lbit, mp[w[u]], );
dfs(ch[u][]);
add(lbit, mp[w[u]], -);
}
if (ch[u][]) {
add(rbit, mp[w[u]], );
dfs(ch[u][]);
add(rbit, mp[w[u]], -);
}
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
cnt = , mp.clear(), vv.clear();
memset(ch, , sizeof (ch));
memset(lbit, , sizeof (lbit));
memset(rbit, , sizeof (rbit));
for (int i = ; i <= n; ++i) {
v[i].clear();
scanf("%d", &w[i]);
num[cnt++] = w[i]; // 将所有的要进行处理的节点重量以及询问的重量离散化
}
scanf("%d", &m);
int a, b, c;
for (int i = ; i < m; ++i) {
scanf("%d %d %d", &a, &b, &c);
ch[a][] = b, ch[a][] = c;
}
int Q;
scanf("%d", &Q);
for (int i = ; i < Q; ++i) {
scanf("%d %d", &a, &b);
v[a].push_back(Node(i, a, b, , ));
num[cnt++] = b;
}
sort(num, num + cnt);
cnt = unique(num, num + cnt) - num; // 离散化之后一共是cnt个元素
for (int i = ; i < cnt; ++i) {
mp[num[i]] = i + ; // 这里加1是为了避免树状数组统计时无法处理0号元素
}
dfs(); // 题目中约定了1为根
for (int i = ; i <= n; ++i) {
for (int j = ; j < (int)v[i].size(); ++j) {
vv.push_back(v[i][j]);
}
}
sort(vv.begin(), vv.end());
for (int i = ; i < (int)vv.size(); ++i) {
printf(vv[i].ansx == - ? "0\n" : "%d %d\n", vv[i].ansx, vv[i].ansy);
}
}
return ;
}

HDU-4606 Occupy Cities

题意:给定N个城市,现在要从这些城市被外星人攻击还是什么的,要去提前占领这些城市,给出N个城市的二维坐标。同时,在地图上存在一些线段栅栏,一条线路不能够直接越过栅栏。现在有P个士兵,每个士兵可以空降到某一坐城市,士兵到达某座城市后,可以前往另外一座城市,在前往城市的路上需要一些食物消耗,每单位距离对应一个单位食物消耗,没新到一个城市,包裹将被重新填充满。所有士兵都配有一个包裹,包裹单位与食物单位。现在列出一个城市占领的先后序列,要求最多使用P个士兵按照这个序列前去占领,问最少的背包容量为多少?

分析:首先只要背包容量够大,那么一个士兵也是能够把所有的城市走遍的。这题一个直接的想法就是去二分枚举背包的容量,然后通过几何加之最短路处理将城市与城市之间的最短距离求出来,再然后根据背包容量构造子图,最后求一个有向无环图的最小路径覆盖数,比较最小路径覆盖数与P的关系即可。

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
struct Point {
double x, y;
Point() {}
Point(double _x, double _y) : x(_x), y(_y) {}
void read() {
scanf("%lf %lf", &x, &y);
}
double operator * (const Point &b) const {
return x*b.y - y*b.x;
}
Point operator - (const Point &b) const {
return Point(x-b.x, y-b.y);
}
}; struct Line {
Point s, e;
Line() {}
Line(Point _s, Point _e) : s(_s), e(_e) {}
}; const int N = ;
const int M = ;
const double eps = 1e-;
int n, m, p, LIM;
Point pt[N*];
int seq[N];
double mp[N*][N*];
char G[N][N];
char vis[N];
int match[N]; inline int sign(const double &x) {
return (x < eps) ? - : (x > eps);
} inline double dist(const Point &a, const Point &b) {
return sqrt(1.0*(a.x-b.x)*(a.x-b.x) + 1.0*(a.y-b.y)*(a.y-b.y));
} void floyd() {
for (int k = ; k <= LIM; ++k) {
for (int i = ; i <= LIM; ++i) {
if (i == k) continue;
for (int j = ; j <= LIM; ++j) {
if (i == j || j == k) continue;
if (sign(mp[i][k] + mp[k][j] - mp[i][j]) < ) {
mp[i][j] = mp[i][k] + mp[k][j];
}
}
}
}
} bool inter(const Line l1, const Line l2) {
return
max(l1.s.x, l1.e.x) > min(l2.s.x, l2.e.x) &&
max(l2.s.x, l2.e.x) > min(l1.s.x, l1.e.x) &&
max(l1.s.y, l1.e.y) > min(l2.s.y, l2.e.y) &&
max(l2.s.y, l2.e.y) > min(l1.s.y, l1.e.y) &&
sign((l2.s-l1.s)*(l1.e-l1.s)) * sign((l2.e-l1.s)*(l1.e-l1.s)) < &&
sign((l1.s-l2.s)*(l2.e-l2.s)) * sign((l1.e-l2.s)*(l2.e-l2.s)) < ;
} void build() {
bool c;
for (int i = ; i <= LIM; ++i) {
for (int j = i+; j <= LIM; ++j) { // 枚举两个城市之间是否有边相连
c = false;
for (int k = , d = ; k <= m; ++k, d+=) {
if (i > n && k == (i-n+)/) continue;
if (j > n && k == (j-n+)/) continue;
if (inter(Line(pt[i], pt[j]), Line(pt[n+d], pt[n+d+]))) {
c = true;
break;
}
}
if (!c) { // 说明没有直线与两个城市之间的连线相交
mp[i][j] = mp[j][i] = dist(pt[i], pt[j]);
}
}
}
floyd();
} bool path(int u) {
for (int v = ; v <= n; ++v) {
if (vis[v] || !G[u][v]) continue;
vis[v] = ;
if (!match[v] || path(match[v])) {
match[v] = u;
return true;
}
}
return false;
} bool Ac(double mid) {
memset(G, , sizeof (G));
memset(match, , sizeof (match));
for (int i = ; i <= n; ++i) { // 有向无环图构造完成
for (int j = i+; j <= n; ++j) {
if (sign(mid - mp[seq[i]][seq[j]]) >= ) {
G[seq[i]][seq[j]] = ;
}
}
}
int cnt = ;
for (int i = ; i <= n; ++i) {
memset(vis, , sizeof (vis));
if (path(i)) ++cnt;
}
return n-cnt <= p;
} double bsearch(double l, double r) {
double mid, ret;
while (r - l >= eps) {
mid = (l + r) / 2.0;
if (Ac(mid)) {
r = mid - eps;
ret = mid;
} else {
l = mid + eps;
}
}
return ret;
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d %d %d", &n, &m, &p);
LIM = n+*m;
for (int i = ; i <= LIM; ++i) {
for (int j = i; j <= LIM; ++j) {
mp[i][j] = mp[j][i] = 1e20;
}
}
for (int i = ; i <= n; ++i) pt[i].read();
for (int i = , j = ; i <= m; ++i, j+=) {
pt[n+j].read(), pt[n+j+].read();
}
for (int i = ; i <= n; ++i) scanf("%d", &seq[i]);
build();
double ret = bsearch(, 1e5);
printf("%.2f\n", ret);
}
return ;
}

2013 Multi-University Training Contest 1的更多相关文章

  1. Integer Partition(hdu4658)2013 Multi-University Training Contest 6 整数拆分二

    Integer Partition Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  2. Partition(hdu4651)2013 Multi-University Training Contest 5

    Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  3. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

  4. Partition(hdu4651)2013 Multi-University Training Contest 5----(整数拆分一)

    Partition Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  5. JSU 2013 Summer Individual Ranking Contest - 5

    JSU 2013 Summer Individual Ranking Contest - 5 密码:本套题选题权归JSU所有,需要密码请联系(http://blog.csdn.net/yew1eb). ...

  6. HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

    Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/500 ...

  8. 2015 Multi-University Training Contest 8 hdu 5390 tree

    tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...

  9. hdu 4946 2014 Multi-University Training Contest 8

    Area of Mushroom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  10. 2016 Multi-University Training Contest 2 D. Differencia

    Differencia Time Limit: 10000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

随机推荐

  1. 【Pro ASP.NET MVC 3 Framework】.学习笔记.8.SportsStore:管理

    管理功能,如何身份认证,对controller和action方法过滤安全的访问,并在用户需要时提供证书. 1 添加分类管理 方便管理的controller,有两类页面,List页面和edit页面. 1 ...

  2. maven手动安装jar到本地仓库

    比如oracle驱动ojdbc5.jar 1,安装MAVEN,并配置系统环境变量 2,将jar文件复制到d: 3,打开cmd窗口,cd到d: 4,执行命令:mvn install:install-fi ...

  3. Oracle 行迁移和行链接

    一.行迁移 1.1.行迁移概念 当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移.一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址.因此整 ...

  4. MyISAM表杂记实验

    一.本文说明 由于刚学mysql所以动手做了一些实验. 二.实验内容 1.验证MyISAM有AUOT_INCREMENT coloumn功能 ----在这里是对现有表t,增加一个主键----mysql ...

  5. Shell 字符串比较

    转自网络 Shell字符串比较 收藏 Shell 中整数比较方法及字符串的比较方法,如等于,不等于,大于,大于等于,小于,等等. 二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别. --- ...

  6. SlickGrid example 5:带子项的展开收缩

    带子项的展开收缩.   代码: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Ty ...

  7. Case of the Zeros and Ones 分类: CF 2015-07-24 11:05 15人阅读 评论(0) 收藏

    A. Case of the Zeros and Ones time limit per test 1 second memory limit per test 256 megabytes input ...

  8. 怎样解决:未找到路径“……”的控制器或该控制器未实现 IController?

    就是要加上new{area=""},比如下面的: @{Html.RenderAction("Cartsummary","ShoppingCart&qu ...

  9. Mysql 升级到 5.6 后插入语句时间字段报错:Incorrect datetime value: '' for column 'createtime'

    今天部署服务器项目运行,当遇见有时间数据对象的插入和更新操作的时候,就报错,如下: Caused by: com.mysql.jdbc.MysqlDataTruncation: Data trunca ...

  10. msm8916 lcd 相关调试点指导

    主要代码:LINUX\android\kernel\arch\arm\boot\dts\qcom\dsi-panel-trust-hx8379c-fwvga-video.dtsiLINUX\andro ...