[CQOI2010] 鼹鼠
考场碰到直接 jj
题目背景是 分形图 + 三角函数 。
一个基本想法就是把空的位置建出来,然后跑搜索,对每个格子求面积。
那么我们知道一个格子的倾斜角度和水的深度,就可以计算出上下左右格子中水的深度。
-
( x , y + 1 ) (x,y+1) (x,y+1): h → max ( 0 , h − sin θ ) h\to \max(0,h-\sin \theta) h→max(0,h−sinθ)

-
( x , y − 1 ) (x,y-1) (x,y−1): h → min ( sin θ + cos θ , h + sin θ ) h\to \min(\sin \theta+\cos \theta,h+\sin \theta) h→min(sinθ+cosθ,h+sinθ)

- ( x − 1 , y ) (x-1,y) (x−1,y) : h → max ( 0 , h − cos θ ) h\to \max(0,h-\cos \theta) h→max(0,h−cosθ)

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)
h→min(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);
}

浙公网安备 33010602011771号