- 注册时间
- 2020-11-9
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 3824
- 在线时间
- 小时
|
楼主 |
发表于 2021-4-16 15:50:10
|
显示全部楼层
本帖最后由 uk702 于 2021-4-16 16:52 编辑
抛砖引玉:写了一段 c 的代码,可能有 bug,初步测试似表明小偷没被抓住的话,通常在100多步内跑出包围圈(至少100步,至多估计是142步)。
请大家检查。
参考 #7 的图,假设小偷位于原点(0,0),6个警察分别占据弧AC的 6 个等分位置:
1)将单位时间分成 100 片;
2) 在每一个时间片内,小偷可以做 3 种操作之一:向上跑(OC的方向),向左跑(OA的方向),45°左上斜向跑,每次跑上0.01个单位长度。
3)警察比较笨,每次他总是设法跑向弧线中离小偷最近的那个点(候选位置是不动,顺时针全速,顺时针半速,逆时针全速,逆时针半速 5 个点之一),警察每次最多只能走 (1/1.1)*(2/Pi) * 0.01 个弧度
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <math.h>
- #define N 5 // 警察的数目
- #define Pi 3.14159265358979
- #define part (1.0/100) // 小偷每步的长度
- #define halfsqrt2 (1.4142135623730950488016887/2.0)
- char traces[1024*1024];
- int main() {
- // 初始化随机种子
- srand((unsigned)time(NULL));
- int num = 0, catch = 0;
- while(1) {
- double p[2]; // 小偷的坐标
- double a[N+1]; // 警察的坐标(弧度,0=0,1=Pi/2)
- p[0] = 0.0; p[1] = 0.0;
- for(int k = 0; k <= N; ++k) {
- a[k] = ((double) k) / N;
- }
- ++num;
- int step = 0;
- while(1) {
- // 计算每个警察和小偷的距离
- for (int k=0; k <= N; ++k) {
- double d = (sin(a[k]*Pi/2)-p[0])*(sin(a[k]*Pi/2)-p[0]) + (cos(a[k]*Pi/2)-p[1])*(cos(a[k]*Pi/2)-p[1]);
- printf("step = %d, 警察[%d] = (%.7f, %.7f), 小偷 = (%.7f, %.7f), 距离 = %.7f \n", step, k, sin(a[k]*Pi/2), cos(a[k]*Pi/2), p[0], p[1], sqrt(d));
- if (d < (part/1.1) * (part/1.1)) {
- ++catch;
- printf("num = %d, catch thief on step %d, percent = %.7f\n", num, step, ((double) catch)/num);
- // for (int t=0; t<step; ++t) { printf("%d ", traces[t]); if (t % 10 == 1) printf("\n"); }
- // printf("\n");
- goto _next;
- }
- }
- // 小偷跑一步
- char di = rand() % 3;
- traces[step] = di;
- // 递增步数
- ++step;
- switch (di) {
- case 0: p[0] += part; break;
- case 1: p[1] += part; break;
- case 2: p[0] += part*halfsqrt2; p[1] += part*halfsqrt2;break;
- }
- // 检查小偷是否跑出包围圈
- if (p[0] * p[0] + p[1]*p[1] > 1.0) {
- printf("num = %d, thief run away on step %d, percent = %.7f\n", num, step, 1.0 - ((double) catch)/num);
- for (int t=0; t<step; ++t) { printf("%d ", traces[t]); if (t % 10 == 9) printf("\n"); }
- printf("\n");
- //goto _next;
- exit(0);
- }
- // 每个警察都跑一步,每一个step,警察最多只能走 (1/1.1)*(2/Pi) * part 个弧度
- // 警察总是跑向离小偷最近的那个点(为简单起见,只考虑不动,顺时针全速,顺时针半速,逆时针全速,逆时针半速 5 个点)
- {
- for (int k=0; k <= N; ++k) {
- double dist = 100.0;
- int select = -2;
- for (int t=-2; t<=2; ++t) {
- double x = a[k] + (1.0/1.1)*(2.0/Pi) * part * (t/2.0);
- double d = (sin(x*Pi/2)-p[0])*(sin(x*Pi/2)-p[0]) + (cos(x*Pi/2)-p[1])*(cos(x*Pi/2)-p[1]);
- if (d < dist) {
- dist = d;
- select = t;
- }
- }
- // 更新警察的位置
- a[k] = a[k] + (1.0/1.1)*(2.0/Pi) * part * (select/2.0);
- }
- // 如果警察扎堆,则强制要求一个跑动的距离
- // for (int t = 0; t < N/2; ++t)
- // if ((a[N/2]-a[t]) < t) a[t] = a[N/2]-((double) t/N);
- // for (int t = N/2+1; t < N; ++t)
- // if ((a[t]-a[N/2]) < t) a[t] = a[N/2]+(t-N/2);
- }
- }
- _next:
- //break;
- ;
- }
- return 0;
- }
复制代码
|
|