问题描述

小强每天会在小区的某些位置摆一些狗盆,并在狗盆里倒入不同口味的狗粮。而所有的流浪狗都会跑到离自己第k近的狗盆那里吃狗粮,一定的跑动可以帮助狗保持身材。

已知小强牌狗粮目前只有10种口味,我们用1,2,3,…,10来表示这些口味。(草莓味是1,西瓜味是2,香橙味是3......)

为了估算每种口味的狗粮每日的需求量,他想知道对于一个在[0,10000]x[0,10000]随机均匀生成的实数坐标(x,y)来说,离它第k近的狗盆里放的狗粮是口味z(z=1...10)的概率是多少。

由于小强最近忙着训练神经网络,他把这个任务交给了你,你能帮他解决吗?

为了简化题目,小区的每个位置可以用坐标(x,y)来表示,坐标范围是[0,10000]x[0,10000]

输入格式

第一行是两个整数n和k,分别表示狗盆的数量和题目描述中的k。

接下来n行,每行有三个整数 X Y Z,分别表示狗盆的坐标(X,Y)和这个狗盆中所放狗粮的口味Z。

输出格式

按顺序输出题中描述的属于口味1~10的概率。

输出的值与正确答案的差的绝对值小于1e-5即可。

样例输入

4 2

0 0 1

0 10000 2

10000 0 3

10000 10000 4

样例输出

0.2500000000

0.2500000000

0.2500000000

0.2500000000

Input文件 dogfood_input.txt

80 23

13 5702 9

2143 9228 3

9904 559 7

5632 858 10

2629 6635 1

9533 9321 5

3417 2051 4

5860 2582 8

8901 8855 5

646 5445 10

3723 3993 3

9460 8418 3

5342 6370 4

5857 3892 2

4453 3001 7

7779 7617 1

6333 6299 10

9508 5811 4

1502 1029 5

1259 6572 2

849 8905 6

5142 8063 4

8736 9776 1

2724 5386 3

5676 7238 10

6521 8374 6

4533 2614 2

5535 6041 8

741 5192 7

1368 6361 3

1967 428 5

4338 374 8

28 4433 9

4793 1407 7

2238 4627 2

4397 3235 2

9715 1681 8

4829 7205 1

7440 874 3

7393 3689 4

8909 9344 3

4794 6390 7

9269 230 6

7271 8835 10

1595 2184 10

7764 9876 5

108 5086 2

3392 7318 7

2157 9471 9

5847 4619 9

1001 417 10

5737 236 5

6374 1349 10

4615 7113 4

8476 8619 7

6977 9068 3

8089 5058 9

1957 9904 10

7791 7207 5

3792 8631 10

6077 2780 3

6101 2758 4

7481 8120 2

6679 2954 1

8001 7276 4

3953 7587 8

9520 3272 6

5848 6982 9

2902 8808 5

9067 8584 5

5674 3275 1

2557 6123 9

4790 2973 2

9429 2741 2

9090 21 8

666 364 4

9372 9724 3

9617 1009 7

950 1963 3

9254 2668 1

解法

有时候一心想着精确解就忘记了近似法,多次模拟求近似值的思想很重要。

megcup不需要提交代码去服务器上运行,只需要提交程序运行结果。

这个问题暴力也是可以解决的,但是需要运行十几分钟。

直接枚举10000x10000个点

#include <set>
#include <map>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> using namespace std; struct Bowl {
int x, y, c;
double dist;
}b[1000]; int n, k, cnt[10]; bool cmp(const Bowl& a, const Bowl& b) {
return a.dist < b.dist;
} double sqr(double x) {
return x * x;
} int main() {
freopen("dogfood_input.txt","r",stdin);
scanf("%d%d", &n, &k);
for (int i = 0; i < n; ++i) {
scanf("%d%d%d", &b[i].x, &b[i].y, &b[i].c);
}
for (int i = 0; i < 10000; ++i) {
printf("%d\n",i);
for (int j = 0; j < 10000; ++j) {
for (int kk = 0; kk < n; ++kk) {
b[kk].dist = sqr(i + 0.5 - b[kk].x) + sqr(j + 0.5 - b[kk].y);
}
sort(b, b + n, cmp);
cnt[b[k - 1].c - 1] ++;
}
}
for (int i = 0; i < 10; ++i) {
printf("%.8lf\n", cnt[i] * 1.0 / 100000000);
}
puts("");
}

如果对精度要求高一些,可以使用随机插点法

使用pair<double,int>可以省掉排序函数cmp。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <thread>
#include <algorithm> using namespace std; const int delta = 4; int n, kkk; int x[100], y[100], z[100];
pair<double, int> dis[100];
int num[100]; void sample() {
double xx, yy;
for (int i = 0; i < 10000; ++i) {
for (int j = 0; j < 10000; ++j) {
for (int d = 0; d < delta; ++d) {//随机插入delta个点
xx = i + 1.0 * rand() / RAND_MAX;
yy = j + 1.0 * rand() / RAND_MAX;
for (int k = 1; k <= n; ++k) {
dis[k].first = (xx - x[k]) * (xx - x[k]) + (yy - y[k]) * (yy - y[k]);
dis[k].second = z[k];
}
sort(dis + 1, dis + n + 1);
num[dis[kkk].second] += 1;
}
}
}
} int main(int argc, char *argv[]) {
//使用一个环境变量判断是否是本地环境(这个变量在本地定义)
#ifdef LOCAL_JUDGE
freopen("dogfood_input.txt", "r", stdin);
freopen("test.out", "w", stdout);
#endif // LOCAL_JUDGE scanf("%d %d", &n, &kkk);
for (int i = 1; i <= n; ++i) {
scanf("%d %d %d", &x[i], &y[i], &z[i]);
}
sample(); int tot = 100000000 * 4;
for (int i = 1; i <= 10; ++i)
printf("%.8f\n", 1.0 * num[i] / tot);
return 0;
}

其实也不一定要均匀取点,有人随机撒点20亿次

#include <iostream>
#include <string>
#include <map>
#include <ctime>
#include <cmath>
#include <vector>
#include <cstdio> using namespace std; int n, k; const int MAXN = 100000;
int a[MAXN][3];
vector<pair<double, int> >v;
double ans[100]; double real()
{
return 10000.0 * rand() / RAND_MAX - 5000;
} int get_ans(double x, double y)
{
v.clear();
for (int i = 0; i < n; i++)
{
double d = pow(a[i][0] - x, 2) + pow(a[i][1] - y, 2);
v.push_back(make_pair(d, a[i][2]));
}
sort(v.begin(), v.end());
return v[k - 1].second;
} void work()
{
double x = real(), y = real();
ans[get_ans(x, y)]++;
ans[get_ans(-x, y)]++;
ans[get_ans(x, -y)]++;
ans[get_ans(-x, -y)]++;
} void print()
{
int tot = 0;
for (int i = 1; i <= 10; i++) tot += ans[i];
for (int i = 1; i <= 10; i++) printf("%.8lf\n", ans[i] / tot);
} int main()
{
srand(time(0));
freopen("dogfood_input.txt", "r", stdin);
cin>>n>>k;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 3; j++) cin >> a[i][j];
a[i][0] -= 5000;
a[i][1] -= 5000;
}
int T = 2000000000;
for (int i = 1; i <= T; i++)
{
work();
if (i % 100000 == 0)
{
cout << "============== " << i << endl;
print();
}
} return 0;
}

既然是K近邻,那么KD树应该能够加速,但是很容易写挫导致还不如不用KD树。

很多时候,我都没有意识到Python有多慢,用C++重写Python之后运行效率的提升可以说是翻天覆地。

算法比赛中,用C++已经成为一种标准,出题人往往不写其它语言的标程,对其它语言的运行时间会高估很多,导致用其他语言很难通过(需要进行很多优化),而用C++暴力有时也能通过。

import numpy as np
from sklearn.neighbors import KDTree a = [int(x) for x in open("dogfood_input.txt").read().split()]
N = a[0]
K = a[1]
points = np.empty((N, 2), dtype=np.int)
flavor = np.empty(N, dtype=np.int)
for i in range(N):
points[i][0] = a[2 + i * 3]
points[i][1] = a[3 + i * 3]
flavor[i] = a[4 + i * 3]
kdt = KDTree(points, metric="euclidean")
cnt = [0] * 11
for i in range(10001):
if i % 10 == 0: print(i)
for j in range(10001):
p = kdt.query([(i, j)], k=K, return_distance=False)
ind = p[0][-1]
x, y = points[ind][0], points[ind][1]
f = flavor[ind]
cnt[f] += 1
s = 1e4 ** 2
for i in range(11):
cnt[i] /= s
print(cnt)

答案

0.08715860

0.15624080

0.11137702

0.16169284

0.07123529

0.02621666

0.09187029

0.08934817

0.09907106

0.10578927

总结

megcup的题目暴力比较多,如果掌握并行化编程,就可以少考虑许多技巧。

Megcup2017 Dogfood的更多相关文章

  1. 《InsideUE4》-4-GamePlay架构(三)WorldContext,GameInstance,Engine

    Tags: InsideUE4 UE4深入学习QQ群: 456247757 引言 前文提到说一个World管理多个Level,并负责它们的加载释放.那么,问题来了,一个游戏里是只有一个World吗? ...

  2. Medusa引擎开源了

    首先贴出 Github地址 然后博客地址 相比于市面上其他的著名游戏引擎,例如Unity,cocos2dx,Unreal,Medusa游戏引擎目前还非常的简陋,目前实现的功能还集中在2D部分,3D的虽 ...

  3. The Google Test and Development Environment (持续更新)

    最近Google Testing Blog上开始连载The Google Test and Development Environment(Google的测试和开发环境),因为blogspot被墙,我 ...

  4. metasploit--exploit模块信息

    Name                                             Disclosure Date  Rank    Description ----           ...

  5. 记录参加QCon的心得

    如有侵权,请告知作者删除.scottzg@126.com 很荣幸参加QCon全球软件开发大会,这里特别感谢我们部门的总经理,也是<互联网广告算法和系统实践>此书的作者王勇睿.因为他我才有这 ...

  6. 什么是MSF

    什么是MSF MSF,即Microsoft Solution Framework,也就是微软推荐的做软件的方法. MSF发展:大约在1994年,微软在总结了自己产品团队的开发经验和教训,以及微软咨询服 ...

  7. 记录参加QCon2017北京站的心得

    如有侵权,请告知作者删除.scottzg@126.com 很荣幸参加QCon全球软件开发大会,这里特别感谢我们部门的总经理,也是<互联网广告算法和系统实践>此书的作者王勇睿.因为他我才有这 ...

  8. IT界的一些朗朗上口的名言

    序 中国有很多古代警世名言,朗朗上口,凝聚了很多故事与哲理.硅谷的互联网公司里头也有一些这样的名言,凝聚了很多公司价值观和做事的方法,对于很多程序员来说,其影响潜移默化.这里收集了一些,如下. Sta ...

  9. day 35 协程与gil概念

    博客链接: http://www.cnblogs.com/linhaifeng/articles/7429894.html 今日概要: 1 生产者消费者模型(补充) 2 GIL(进程与线程的应用场景) ...

随机推荐

  1. 使用C#开发一个简单的P2P应用

    作者: 刘彦青 本篇文章讨论了一种设计P2P网络应用程序的简单方法. 尽管有许多P2P网络不需要索引服务器或中央服务器,各客户机之间可以互相直接通讯,但下面的图1还是显示了P2P网络的基本工作原理,一 ...

  2. 用于文本分类的RNN-Attention网络

    用于文本分类的RNN-Attention网络 https://blog.csdn.net/thriving_fcl/article/details/73381217 Attention机制在NLP上最 ...

  3. TensorFlow练习7: 基于RNN生成古诗词

      http://blog.topspeedsnail.com/archives/10542 主题 TensorFlow RNN不像传统的神经网络-它们的输出输出是固定的,而RNN允许我们输入输出向量 ...

  4. editplus教程

    Editplus 3.0 开发ext 教程 使用Editplus配置轻型的PHP调试环境 Editplus已经使用了很多年,一直很喜欢这个小巧.精致的文本编辑器,比起ZenStudio这样庞大的IDE ...

  5. HTTP协议综合

    1.用浏览器模拟各种User Agent 测试页面的时候经常需要不同的User Agent,Firefox.Chrome浏览器就可以完美的模拟出各种User Agent.User Agent Swit ...

  6. php获取当前时间的方法

    1.获取当前时间 date('Y-m-d H:i:s', time())   2.字符串转时间 date('Y-m-d H:i:s',strtotime('2018-8-21 22:00:00'))

  7. LintCode: Delete Node in the Middle of Singly Linked List

    开始没看懂题目的意思,以为是输入一个单链表,删掉链表中间的那个节点. 实际的意思是,传入的参数就是待删节点,所以只要把当前节点指向下一个节点就可以了. C++ /** * Definition of ...

  8. Windows 之 可以Ping通服务器但无法使用服务器连接的共享打印机

    故障现象:一个公司内部局域网中,一台电脑可以Ping通服务器,但无法使用服务器连接的共享打印机. 故障分析与排除:根据故障现象分析,由于客户端可以Ping通服务器,说明网络连接正常,故障可能是由客户端 ...

  9. Linux shell中一些参数与变量简介

    linux中shell变量$#,$@,$0,$1,$2,$!,$$,$*,$-,$@......等很多个,很容易记错,这里再次整理一下,相关含义解释如下,并附上一个实践截图. 多看几次,多用几次,应该 ...

  10. iOS webservice SOAP 请求

    1. Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的.专门的第三方软件或硬件, 就可相互交换数据或集成.依据Web Service规范实施的应用之间, 无论它们所使用的语 ...