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

View Code

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 = 105;
const int M = 105;
const double eps = 1e-6;
int n, m, p, LIM;
Point pt[N*3];
int seq[N];
double mp[N*3][N*3];
char G[N][N];
char vis[N];
int match[N];inline int sign(const double &x) {return (x < eps) ? -1 : (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 = 1; k <= LIM; ++k) {for (int i = 1; i <= LIM; ++i) {if (i == k) continue;for (int j = 1; j <= LIM; ++j)  {if (i == j || j == k) continue;if (sign(mp[i][k] + mp[k][j] - mp[i][j]) < 0) {mp[i][j] = mp[i][k] + mp[k][j];}}}}
}bool inter(const Line l1, const Line l2) {returnmax(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)) < 0 &&sign((l1.s-l2.s)*(l2.e-l2.s)) * sign((l1.e-l2.s)*(l2.e-l2.s)) < 0;
}void build() {bool c;for (int i = 1; i <= LIM; ++i) {for (int j = i+1; j <= LIM; ++j) { // 枚举两个城市之间是否有边相连 c = false;for (int k = 1, d = 1; k <= m; ++k, d+=2) {if (i > n && k == (i-n+1)/2) continue;if (j > n && k == (j-n+1)/2) continue;if (inter(Line(pt[i], pt[j]), Line(pt[n+d], pt[n+d+1]))) {c = true;break;}}if (!c) { // 说明没有直线与两个城市之间的连线相交 mp[i][j] = mp[j][i] = dist(pt[i], pt[j]);}}}floyd();
}bool path(int u) {for (int v = 1; v <= n; ++v) {if (vis[v] || !G[u][v]) continue;vis[v] = 1;if (!match[v] || path(match[v])) {match[v] = u;return true;}}return false;
}bool Ac(double mid) {memset(G, 0, sizeof (G));memset(match, 0, sizeof (match));for (int i = 1; i <= n; ++i) { // 有向无环图构造完成 for (int j = i+1; j <= n; ++j) {if (sign(mid - mp[seq[i]][seq[j]]) >= 0) {G[seq[i]][seq[j]] = 1;}}}int cnt = 0;for (int i = 1; i <= n; ++i) {memset(vis, 0, 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+2*m;for (int i = 1; i <= LIM; ++i) {for (int j = i; j <= LIM; ++j) {mp[i][j] = mp[j][i] = 1e20;}}for (int i = 1; i <= n; ++i) pt[i].read();for (int i = 1, j = 1; i <= m; ++i, j+=2) {pt[n+j].read(), pt[n+j+1].read();}for (int i = 1; i <= n; ++i) scanf("%d", &seq[i]);build();double ret = bsearch(0, 1e5);printf("%.2f\n", ret);}return 0;
}

View Code

转载于:https://www.cnblogs.com/Lyush/p/3212590.html

2013 Multi-University Training Contest 1相关推荐

  1. Sichuan University Programming Contest 2018 Preliminary

    嗯为了防止大家AK,所以这次的A题和K题我们就当做不存在好了! 经历了昨天写了两个多小时的博客没保存的心态炸裂,今天终于下了个Markdown.所以我猜这篇的格式应该会更好看一点! 好吧废话不多说 题 ...

  2. HDU 6091 - Rikka with Match | 2017 Multi-University Training Contest 5

    思路来自 某FXXL 不过复杂度咋算的.. /* HDU 6091 - Rikka with Match [ 树形DP ] | 2017 Multi-University Training Conte ...

  3. HDU 6051 - If the starlight never fade | 2017 Multi-University Training Contest 2

    /* HDU 6051 - If the starlight never fade [ 原根,欧拉函数 ] | 2017 Multi-University Training Contest 2 题意: ...

  4. HDU 6058 - Kanade's sum | 2017 Multi-University Training Contest 3

    /* HDU 6058 - Kanade's sum [ 思维,链表 ] | 2017 Multi-University Training Contest 3 题意:给出排列 a[N],求所有区间的第 ...

  5. 2017 Multi-University Training Contest - Team 3 Kanade's sum hd6058

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6058 题目: Kanade's sum Time Limit: 4000/2000 MS (J ...

  6. 2018 Multi-University Training Contest 3 Problem F. Grab The Tree 【YY+BFS】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6324 Problem F. Grab The Tree Time Limit: 2000/1000 MS ...

  7. hdu 4925 Apple Tree--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 Apple Tree Time Limit: 2000/1000 MS (Java/Others ...

  8. HUST-2015 Multi-University Training Contest 9

    2015 Multi-University Training Contest 9 solutions BY xudyh 1001.Expression 记dp_{l,r}dp​l,r​​表示l,rl, ...

  9. 2018 Multi-University Training Contest 4 Problem E. Matrix from Arrays 【打表+二维前缀和】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6336 Problem E. Matrix from Arrays Time Limit: 4000/20 ...

  10. 2017 Multi-University Training Contest - Team 1

    2017 Multi-University Training Contest - Team 1 01     签到的 #include<bits/stdc++.h> using names ...

最新文章

  1. ologit模型与logit_Stata-多元 Logit 模型详解 (mlogit)
  2. 怎么做好企业IT运维工作
  3. C语言精要总结-指针系列(二)
  4. 水题:P2799 国王的魔镜
  5. 基于IdentityServer的系统对接微信公众号
  6. 【jq】c#零基础学习之路(1)Hello World!
  7. 13.表格标签及其应用实例
  8. 外部仓库_一键同步!CODING 现已支持导入 GitHub 仓库
  9. Nginx常见错误码解决方案
  10. 使用python开发windows应用程序
  11. Atitit 研发管理之道 attilax总结 艾龙 著 研发管理 1 简介 1 基本理念 2 基本原则 2 内容 3 团队建设 4 流程设计 4 成本管理 4 项目管理 4 绩效管理 4 风险管理
  12. html浅色_html文本字体浅色
  13. 微信飞机大战游戏开发
  14. python词库介绍_解析搜狗词库(python)
  15. 自己对war包解压的误区
  16. PHP全部导出excel方法与批量导出超简单方法!
  17. tolower c语言,C 库函数 tolower() 使用方法及示例
  18. 【Python】唯品会购买商品
  19. 基于单片机的电流检测仿真设计(#0041)
  20. 华为Android10版怎么截屏,华为畅享10e怎么截屏?畅享10e多种屏幕截图方法

热门文章

  1. android 如何正确使用 泛型 和 多参数 “偷懒”
  2. Android之notificaction使用
  3. svn   /lib64/libz.so.1: no version information available
  4. 别人的一句话影响了我好几年
  5. 设计模式之——原型模式
  6. 2.2创建Spring数据REST服务
  7. 【渝粤教育】国家开放大学2018年秋季 0538-21T社区护理 参考试题
  8. 【渝粤题库】陕西师范大学800002 地球概论
  9. 一种修复WSL下linux系统问题的方法
  10. 怎么加入链接,可以让微信浏览器直接提示跳出另一个浏览器查看