JZOJsenior4777.【NOIP2016提高A组模拟9.14】灌水

本文介绍了一种使用深度优先搜索(DFS)解决特定问题的方法。通过分析输入数据,利用DFS遍历矩阵来确定可达区域,并计算相应的贡献值。文章详细解释了算法实现过程及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

problem

Description

Input

Output

Sample Input

1 2
01
4
0 0
2 0
0 1
0 2

Sample Output

0.7854
4.8584
0.0000
4.8584

Data Constraint


analysis

(在考场上能用dfs切掉这道题的小伙子有出息)

其实题目有点绕口,我们把它看成n×m或者2n×2m的矩阵都可以,你爱咋样咋地
首先如果(x+y)mod2=1那么说明倒在了隔板上就输出0.0000

接着考虑dfs,用dfs从洒下点开始遍历整个矩阵,把能流到的格子全部做记号
因为不同格子流到不同格子的贡献是不一样的,遍历的时候我们打上不同方案标记,dfs后扫一遍整个矩阵即可
打起来可能比较烦,所以还是习惯就好吧

时间复杂度O(QNM)O(4QNM)


code

const
        fx:array[1..8,1..2]of longint=((-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1));
        fy:array[1..4,1..2]of longint=((-1,-1),(-1,0),(0,-1),(0,0));
        g:array[1..2,1..2]of longint=((1,-1),(1,1));
var
        a:array[0..500,0..500]of longint;
        bz,bz1:array[0..500,0..500]of boolean;
        s:array[0..100000,0..2]of longint;
        n,m,q,i,j,x,y,z,zz:longint;
        ans:extended;
        ch:char;

procedure readin();
begin
                        read(ch);
                        x:=(i-1)*2;
                        y:=(j-1)*2;
                        bz1[x+1,y]:=true;
                        bz1[x,y+1]:=true;
                        bz1[x+1,y+2]:=true;
                        bz1[x+2,y+1]:=true;
                        if ch='0' then
                        begin
                                a[x,y]:=1;
                                a[x+1,y+1]:=2;
                        end
                        else
                        begin
                                a[x,y+1]:=3;
                                a[x+1,y]:=4;
                        end;
end;

procedure dfs(i,j:longint);
var
        k,x,y:longint;
begin
        for k:=1 to 8 do
        begin
                x:=i+fx[k,1];
                y:=j+fx[k,2];
                if (x<0)or(y<0)or(x>n*2)or(y>m*2)then continue;
                if bz[x,y]then continue;
                if (x<i)and(y<j)and(a[i-1,j-1]>0)then continue;
                if (x<i)and(y>j)and(a[i-1,j]>0)then continue;
                if (x>i)and(y<j)and(a[i,j-1]>0)then continue;
                if (x>i)and(y>j)and(a[i,j]>0)then continue;
                inc(z);
                s[z,1]:=x;
                s[z,2]:=y;
                bz[x,y]:=true;
                dfs(x,y);
        end;
end;

procedure doit();
begin
                readln(x,y);
                bz:=bz1;
                if bz1[x,y] then
                begin
                        writeln('0.0000');
                        exit;
                end;
                bz[x,y]:=true;
                z:=1;
                s[z,1]:=x;
                s[z,2]:=y;
                dfs(x,y);
                zz:=z;
                fillchar(bz,sizeof(bz),0);
                for i:=1 to z do bz[s[i,1],s[i,2]]:=true;
                ans:=0;
                for i:=1 to z do
                begin
                        for j:=1 to 2 do
                                if bz[s[i,1]+g[j,1],s[i,2]+g[j,2]] then ans:=ans+1;
                        for j:=1 to 4 do
                        begin
                                x:=s[i,1]+fy[j,1];
                                y:=s[i,2]+fy[j,2];
                                if (x<0)or(y<0)or(x>n*2)or(y>m*2)then continue;
                                if (j=1)and(a[x,y]=1)then ans:=ans+1-0.25*pi
                                else if (j=1)and(a[x,y]=2)then ans:=ans+0.25*pi
                                else if (j=2)and(a[x,y]=3)then ans:=ans+1-0.25*pi
                                else if (j=2)and(a[x,y]=4)then ans:=ans+0.25*pi
                                else if (j=3)and(a[x,y]=3)then ans:=ans+0.25*pi
                                else if (j=3)and(a[x,y]=4)then ans:=ans+1-0.25*pi
                                else if (j=4)and(a[x,y]=1)then ans:=ans+0.25*pi
                                else if (j=4)and(a[x,y]=2)then ans:=ans+1-0.25*pi;
                        end;
                end;
                writeln(ans:0:4);
end;

begin
        assign(input,'flooding.in');reset(input);
        assign(output,'flooding.out');rewrite(output);
        //assign(input,'readin.pas');reset(input);
        readln(n,m);
        for i:=1 to n do
        begin
                for j:=1 to m do readin;
                readln;
        end;
        readln(q);
        while q>0 do
        begin
                dec(q);
                doit();
        end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值