[CQOI2010] 鼹鼠

考场碰到直接 jj

题目背景是 分形图 + 三角函数

一个基本想法就是把空的位置建出来,然后跑搜索,对每个格子求面积。

那么我们知道一个格子的倾斜角度和水的深度,就可以计算出上下左右格子中水的深度。

  1. ( x , y + 1 ) (x,y+1) (x,y+1) h → max ⁡ ( 0 , h − sin ⁡ θ ) h\to \max(0,h-\sin \theta) hmax(0,hsinθ)
    请添加图片描述

  2. ( x , y − 1 ) (x,y-1) (x,y1) h → min ⁡ ( sin ⁡ θ + cos ⁡ θ , h + sin ⁡ θ ) h\to \min(\sin \theta+\cos \theta,h+\sin \theta) hmin(sinθ+cosθ,h+sinθ)

请添加图片描述

  1. ( x − 1 , y ) (x-1,y) (x1,y) h → max ⁡ ( 0 , h − cos ⁡ θ ) h\to \max(0,h-\cos \theta) hmax(0,hcosθ)

请添加图片描述
4. ( x + 1 , y ) (x+1,y) (x+1,y) h → min ⁡ ( sin ⁡ θ + cos ⁡ θ , h + cos ⁡ θ ) h\to \min(\sin \theta+\cos\theta,h+\cos\theta) hmin(sinθ+cosθ,h+cosθ)
请添加图片描述

总结:影响淹没面积的因素主要是 容器的形状倾斜角度 。对于不同的容器,要具体分析,定性(升高还是降低啊,会不会被容器的形状阻隔啊) + 定量分析(抽取一个方格进行研究,确定水位上升的具体值)。

最后根据每个方格中水的深度算淹没面积。当 >45 时, sin 和 cos 要颠倒一下。

注意精度问题 qwq 。

#include<bits/stdc++.h>
#define db double
using namespace std;
const int N=1<<12;
int n,du,vis[N][N],to[N][N],f[15];
db res;
db pi=atan(1)*4,sx,cx;
db calc(db h) {
	if(du<=45) {
		if(h<=sx) return h*h;
		if(h<=cx) return (2*h-sx)*sx;
		h=sx+cx-h;
		return 2*sx*cx-h*h;
	}
	else {
		if(h<=cx) return h*h;
		if(h<=sx) return (2*h-cx)*cx;
		h=sx+cx-h;
		return 2*sx*cx-h*h;
	}
}
void dfs(int x,int y,db h) {
	if(h<=0) return;
	h=min(h,sx+cx);
	to[x][y]=1,res+=(du==0)?1:calc(h);
	if(x>1&&!to[x-1][y]&&vis[x-1][y]) dfs(x-1,y,h+cx);
	if(x<f[n]-1&&!to[x+1][y]&&vis[x+1][y]) dfs(x+1,y,h-cx);
	if(y>1&&!to[x][y-1]&&vis[x][y-1]) dfs(x,y-1,h+sx);
	if(y<f[n]-1&&!to[x][y+1]&&vis[x][y+1]) dfs(x,y+1,h-sx);
}
int main() {
	for(int i=0;i<=12;i++) f[i]=1<<i;
	scanf("%d%d",&n,&du);
	sx=sin(pi/180*du),cx=cos(pi/180*du);
	vis[1][1]=1;
	for(int siz=2;siz<=n;siz++) {
		for(int i=f[siz]-1;i>=f[siz-1]+1;i--) {
			for(int j=1;j<=f[siz-1]-1;j++) {
				vis[i][j]=!vis[f[siz-1]-j][i-f[siz-1]];
			}
			for(int j=f[siz-1]+1;j<=f[siz]-1;j++) {
				vis[i][j]=!vis[j-f[siz-1]][i-f[siz-1]];
			}
		}
		for(int i=1;i<=f[siz-1]-1;i++) {
			for(int j=f[siz-1]+1;j<=f[siz]-1;j++) {
				vis[i][j]=vis[i][j-f[siz-1]];
			}
		}
		for(int i=1;i<=f[siz]-1;i++) {
			vis[f[siz-1]][i]=1;
		}
		for(int i=f[siz]-1;i>=f[siz-1];i--) {
			vis[i][f[siz-1]]=1;
		}
	}
	for(int i=1;i<=f[n]-1;i++) {
	     //容器开口的深度为 cos \theta
		if(vis[f[n]-1][i]) dfs(f[n]-1,i,cx);
	}
	if(du!=0) res/=2*sx*cx;
	printf("%.6lf",res);
}
posted @   仰望星空的蚂蚁  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
点击右上角即可分享
微信分享提示