你要在一片菜地里捉兔子。

菜地形如一个一个 N×M 的长方形网格,每个顶点要么是空的,要么有一个兔子洞。在每个洞里有恰好 44 只兔子。在土地的四个角都设置了逮兔陷阱(陷阱在坐标 [0,0],[0,M],[N,0],[N,M] 上)。

你有一个彩弹枪和 K 颗彩弹,其中 K 是兔子洞的个数。所有的彩弹颜色都不一样,它们编号从 1 到 K 。你可以往任意兔子洞射一个彩弹。射出之后,该兔子洞的所有兔子都被染成彩弹的颜色,然后都跑出来,沿着四个方向逃窜。全部四只兔子的速度相同,兔子只能沿着网格边界跑。

在移动的过程中,每只兔子都在顶点上或者在边上会留下脚印。但是,在任意顶点或边上,只有最早的脚印是可见的。当一只兔子进入一个已经被染色的顶点时,它会用以下方法选择方向:如果在它前面的那条边与它现在所在的点的颜色不同,它就会顺时针旋转90度,直到颜色相同为止。旋转不耗时间。旋转后,兔子以原速度继续跑。

当兔子遇到网格边界时,它会顺时针旋转90 度继续跑,直到它掉进陷阱。兔子掉进陷阱就认为被抓住了。

如果一只兔子在跑的过程中,见到一个非空的兔子洞,它会立即通知(不耗时间)洞里的所有兔子从秘密隧道逃走,这个洞里的兔子永远都不会在土地中出现。通知洞内兔子后,该兔子仍继续跑。

你的行动是:随机往某个非空的兔子洞射一颗彩弹,然后等待出来的所有兔子都被抓住,再随机往另一个非空兔子洞射一颗,再等 ⋯⋯⋯⋯ 直到所有兔子洞都空为止。每一次你选择每个非空兔子洞的概率都是均等的。

现在,你的任务是求出所有跑出来的兔子从跑出来的时刻起至被抓住的路径之和的数学期望 L 。

考试感想

作为NOIP模拟赛的T1,竟然是全场提交数最少的一道题,而且我觉得暴力比正解还难写
PS:这场10联题目名叫《题》《目》《不》《难》,结果全场第一才180分,要知道原来就算题目再难也还是有300+或者AK的
不过看了题解觉得T1还是可以做的

解题思路

设 F [ i ] [ j ] [ l ] [ r ] F[i][j][l][r] F[i][j][l][r]表示这一块矩形内的期望步数,我们为了维护 F F F,还需要开个数组 G [ i ] [ j ] [ l ] [ r ] [ 0 / 1 / 2 / 3 ] G[i][j][l][r][0/1/2/3] G[i][j][l][r][0/1/2/3],表示分别到达这块矩形四个顶点的期望步数
画个图,我们给这个网格的四个顶点这样顺序标成 0 、 1 、 2 、 3 0、1、2、3 0、1、2、3

然后我们枚举这个矩形内第一个被攻击的兔子洞,发现这个兔子洞的兔子把矩形分成了四个子矩形,且这个兔子洞的路线已经限定了子矩形中的兔子最终会到达子矩形的四个顶点,这也就是最优子结构,可以进行动态规划

先考虑左上角的矩阵,我们看这个矩形内的兔子跑到了哪里
先考虑G数组的更新
我们可以发现左上角子矩形的0点转移到了当前点的1点,子矩形的1号点现在还在1点,子矩形的2号点现在转移到了当前矩形的2号点,子矩形的三号点转移到了当前矩形的0号点(图中绿色剪头)

 G[x][0]+=G[y][3];G[x][1]+=(G[y][0]+G[y][1]);G[x][2]+=G[y][2];

接着思考F数组的转移,设枚举的第一个兔子洞是(i,j)

我们先加上子矩形中的步数

F[x]+=F[y]

这样可以算出每个洞中的兔子走的步数,乘上对应的G就是这个子矩形内所有兔子的步数,注意边界上的兔子洞不能转移,因为题目限制经过的兔子洞中的兔子不会在跑,而这个边界正是你枚举的第一个兔子洞中的兔子的行进路线,所以不能转移

 int y=note[Up][i][Left][j];F[x]+=F[y];G[x][0]+=G[y][3];G[x][1]+=(G[y][0]+G[y][1]);G[x][2]+=G[y][2];F[x]+=G[y][0]*(i-Up);F[x]+=G[y][2]*(Right-j);F[x]+=G[y][3]*(Down-i+j-Left);

对于其余三个矩形类似处理,可以得到下面的转移式

         int y=note[Up][i][Left][j];F[x]+=F[y];G[x][0]+=G[y][3];G[x][1]+=(G[y][0]+G[y][1]);G[x][2]+=G[y][2];F[x]+=G[y][0]*(i-Up);F[x]+=G[y][2]*(Right-j);F[x]+=G[y][3]*(Down-i+j-Left);y=note[Up][i][j][Right];F[x]+=F[y];G[x][1]+=G[y][0];G[x][2]+=(G[y][2]+G[y][1]);G[x][3]+=G[y][3];F[x]+=G[y][1]*(Right-j);F[x]+=G[y][3]*(Down-i);F[x]+=G[y][0]*(j-Left+i-Up);y=note[i][Down][Left][j];F[x]+=F[y];G[x][0]+=(G[y][0]+G[y][3]);G[x][1]+=G[y][1];G[x][3]+=G[y][2];F[x]+=G[y][1]*(i-Up);F[x]+=G[y][2]*(Right-j+Down-i);F[x]+=G[y][3]*(j-Left);y=note[i][Down][j][Right];F[x]+=F[y];G[x][0]+=G[y][0];G[x][2]+=G[y][1];G[x][3]+=(G[y][3]+G[y][2]);F[x]+=G[y][0]*(j-Left);F[x]+=G[y][1]*(Right-j+i-Up);F[x]+=G[y][2]*(Down-i);

最后是当前兔子洞的贡献
乘上这个概率, 1 c n t \frac{1}{cnt} cnt1​,然后考虑第一个兔子洞的路线,如果平移一下可以发现,四个边界肯定都要走一次,所以

 F[x]=F[x]/(db)cnt+2*(Right-Left+Down-Up);

然后是G,发现当前兔子洞使四个角落的点都多了一只兔子

 for(int i=0;i<4;i++)G[x][i]=G[x][i]/(db)cnt+1;

至于整体的转移,可以记忆化搜索,也可以类似区间DP,从小到大枚举举行的长宽,也就是二维区间DP

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
const int N = 1005;
db F[N*N],G[N*N][4];
int note[50][50][50][50];
int n,m,k,tot=0;
int rab[50][50];
void dp(int Left,int Right,int Up,int Down)
{int cnt=0;for(int i=Up+1;i<Down;i++)for(int j=Left+1;j<Right;j++)if(rab[i][j]) cnt++;if(cnt==0) return;int x=note[Up][Down][Left][Right];for(int i=Up+1;i<Down;i++){for(int j=Left+1;j<Right;j++){if(!rab[i][j]) continue;int y=note[Up][i][Left][j];F[x]+=F[y];G[x][0]+=G[y][3];G[x][1]+=(G[y][0]+G[y][1]);G[x][2]+=G[y][2];F[x]+=G[y][0]*(i-Up);F[x]+=G[y][2]*(Right-j);F[x]+=G[y][3]*(Down-i+j-Left);y=note[Up][i][j][Right];F[x]+=F[y];G[x][1]+=G[y][0];G[x][2]+=(G[y][2]+G[y][1]);G[x][3]+=G[y][3];F[x]+=G[y][1]*(Right-j);F[x]+=G[y][3]*(Down-i);F[x]+=G[y][0]*(j-Left+i-Up);y=note[i][Down][Left][j];F[x]+=F[y];G[x][0]+=(G[y][0]+G[y][3]);G[x][1]+=G[y][1];G[x][3]+=G[y][2];F[x]+=G[y][1]*(i-Up);F[x]+=G[y][2]*(Right-j+Down-i);F[x]+=G[y][3]*(j-Left);y=note[i][Down][j][Right];F[x]+=F[y];G[x][0]+=G[y][0];G[x][2]+=G[y][1];G[x][3]+=(G[y][3]+G[y][2]);F[x]+=G[y][0]*(j-Left);F[x]+=G[y][1]*(Right-j+i-Up);F[x]+=G[y][2]*(Down-i);}}F[x]=F[x]/(db)cnt+2*(Right-Left+Down-Up);for(int i=0;i<4;i++)G[x][i]=G[x][i]/(db)cnt+1;
}
int main()
{   cin>>n>>m>>k;for(int i=1;i<=k;i++){int x,y;scanf("%d%d",&x,&y);rab[x][y]=1;}for(int i=0;i<=n;i++)for(int j=i;j<=n;j++)for(int k=0;k<=m;k++)for(int l=k;l<=m;l++)note[i][j][k][l]=++tot;for(int len1=1;len1<=n;len1++)for(int len2=1;len2<=m;len2++)for(int i=0;i+len1<=n;i++)for(int j=0;j+len2<=m;j++)dp(j,j+len2,i,i+len1);printf("%.15lf",F[note[0][n][0][m]]);return 0;
}

ZROI 2021 10联day8 T1 题(期望+二维区间DP)相关推荐

  1. 2021大厂Java面试真题(二)

    2021大厂Java面试真题(二) 2021 [阿里]面试真题: 1.TCP 和 UDP 区别? TCP 基于连接,UDP 基于无连接. TCP 要求系统资源较多,UDP 较少. UDP 程序结构较简 ...

  2. 第2章【思考与练习1】一维数组访问,在subjects数组中选择并显示序号1、2、4门课的名称。二维数组访问,选择并显示scores数组的1、4行。生成由整数10~19组成的2×5的二维数组

    P25思考与练习1 1.一维数组访问. 1)在subjects数组中选择并显示序号1.2.4门课的名称,使用倒序索引选择并显示names数组中"方绮雯". 2)选择并显示names ...

  3. 【每日DP】day 10、P1005 矩阵取数游戏【区间DP+高精(python)】难度⭐⭐⭐★

    P1005 矩阵取数游戏 输入 2 3 1 2 3 3 4 2 输出 82 说明/提示 NOIP 2007 提高第三题. 数据范围: 60%60\%60% 的数据满足:1≤n,m≤301\le n,m ...

  4. 剑指offer刷题(java)|二维数组中的查找|替换空格|leetcode刷题

    文章目录 前言 一.二维数组中的查找 题目 题解一 题解二 题解三 二.替换空格 题目 题解一 题解二 题解三 前言 本文主要是写了我做算法题的思路以及对其他优秀题解的自我理解. 一.二维数组中的查找 ...

  5. C语言 基础60题(2)——二维数组操作

    本篇内容主要是是对二维数组操作,掌握二维数组作为参数传递时,如何用指针表示. 第10题 double  sum_2diagonal(double* array_2d,  unsigned int m, ...

  6. 《剑指offer》第四题(二维数组中的查找)

    // 二维数组中的查找 // 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按 // 照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个 // 整数,判断数组 ...

  7. [剑指offer]面试题第[1]题[JAVA][二维数组中的查找][数组][二分]

    [问题描述] 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...

  8. BugkuCTF-MISC题普通的二维码

    考点在八进制转字符串 下载文件file.zip解压得到一张二维码,扫描没有flag 通过010editor打开,在尾部有一串数字 字符串为: 14615414114717311014116614513 ...

  9. 剑指offer刷题 04. 二维数组中的查找

    剑指 Offer 04. 二维数组中的查找 1. 问题描述 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个高效的函数,输入这样的一 ...

最新文章

  1. Silverlight4.0(9) 之 分页控件轻量级的Session
  2. 2批量批量查询数据插入数据_Excel如何快速对数据批量查询,vlookup+match函数高效完成工作...
  3. .Net之配置文件自定义
  4. java 字符串文字筛选_重新开始Java的原始字符串文字讨论
  5. java11创建项目_2019-04-11 使用IDEA创建SpringBoot项目
  6. 谈一谈HTTP中Get与Post的区别与主要应用场景
  7. mac ssh客户端_Electerm for Mac(ssh客户端)
  8. 大数据实践的6个阶段
  9. Java SecurityManager checkMemberAccess()方法与示例
  10. 仿网易云手机版代码_网易uu加速器官网下载-网易uu加速器手机版下载
  11. android脚本需语言,Android中使用脚本语言Lua
  12. VC2005-应用程序正常初始化失败-0xc0150002
  13. 微信扫二维码下载apk跳转浏览器打开的方式(及微信屏蔽下载解决方案)
  14. avue一些隐藏的配置
  15. 深入Flutter(四) Infinite scrolling -- 无限滚动
  16. BP客户主数据信用数据批量修改
  17. 哔哩哔哩 2019秋招编程题---山寨金闪闪
  18. 【洛谷题解】P1255 数楼梯
  19. 浙江大学 工程伦理 第八单元测试答案
  20. 华数机器人旋转编程_用户手册-华数机器人.PDF

热门文章

  1. 02 Python turtle绘制丘比特爱心
  2. 男人深爱老婆的96个经典细节
  3. 还想着永久在家办公?微软CEO:我自己都睡着了
  4. Microbiome:微生物在植物世代之间的旅程
  5. OSChina 周二乱弹 —— 记一次难忘的通勤经历
  6. Word设置页眉页脚技巧!
  7. JQuery使用——网页作业
  8. 第33章 MySQL 导出数据教程
  9. 在信息泄露事件后 雅虎关闭邮件自动转发功能
  10. 计算机快捷键任务管理器,任务管理器快捷键,小编告诉你电脑如何打开任务管理器...