P2472 [SCOI2007]蜥蜴

以前做过一道类似的题目:

\[\text JZOJ\ 5948 \]

\(X\) 的国家正在遭受袭击,必须抽调一些魂师上前线增援。
到前线用时最短的路上有一条宽度为 \(N\) 米的河,而前来增援的魂师每飞行 \(L\) 米就必须在一片荷叶上休息一下,才能够继续飞行。当然,魂师们也可以选择没飞够 \(L\) 米就先休息一下,但不能一次飞超过 \(L\) 米。
距离河的一侧距离为 \(i\) 的荷叶共有 \(Ai\) 片,每片荷叶在有魂师停于上方休息后, 就会沉入水底,不能够再供其他魂师休息。
现在小 \(X\) 想要知道,至多有多少名魂师能够抵达前线。

条件

  • 有一定的跳跃距离
  • 每一个荷叶有一定的跳跃次数

那就很简单了吗,每一个荷叶往它的最大跳跃距离连边然后跑最大流。

然后会错。

仔细一看要拆点,因为荷叶要限制自己 (并不是什么裂点还有什么乱七八糟的东西,不懂的可以翻阅我的博客)

然后 \(80\) 分,仔细看数据: 对于 \(100\)% 的数据,\(1≤L<N≤10^5\),\(0≤Ai≤10^4\)

最大流瞬间咕咕,需要 \(DP\)

这道题就是上面那道题的加强版,变成了二维。然而 \(2007\) 年的省选是那么的水。

按往常一样先画图,再连边 : (下面是一个九宫格版的数据)

要注意是距离\(d\) ! 然后要搞懂求距离小于 \(d\) 的公式 (没仔细看被刷 低 \(AC\) 率了)

然后就跑 \(ISAP\) 就好啦!

// luogu-judger-enable-o2
Uses math;

var
    value,reach,next,from:array[-1..210000] of longint;
    id:array[-1..41,-1..41,1..2] of longint;
    gap,dis,cnt:array[-1..81000] of longint;
    d,n,m,l,r,k,i,j,sum,tot,sink,source,number,matrix,maxflow,lizard:longint;
    s:ansistring;

procedure add(l,r,sum:longint);
begin
    inc(tot); from[tot]:=l; reach[tot]:=r; value[tot]:=sum; next[tot]:=cnt[l]; cnt[l]:=tot;
    inc(tot); from[tot]:=r; reach[tot]:=l; value[tot]:=8-8; next[tot]:=cnt[r]; cnt[r]:=tot;
end;

function Dfs(now,flow:longint):longint;
var i,k,mindis,ret:longint;
begin
    mindis:=n-1; ret:=flow;
    if now=sink then exit(flow);
    i:=cnt[now];
    while i<>-1 do
    begin
        if value[i]>0 then
        begin
            if dis[now]=dis[reach[i]]+1 then
            begin
                k:=Dfs(reach[i],min(ret,value[i]));
                dec(value[i],k);inc(value[i xor 1],k);
                dec(ret,k);
                if dis[source]>=n then exit(flow-ret);
                if ret=0 then break;
            end;
             mindis:=min(mindis,dis[reach[i]]);
        end;
        i:=next[i];
    end;
    if ret=flow then
    begin
        dec(gap[dis[now]]);
        if gap[dis[now]]=0 then dis[source]:=n;
        dis[now]:=mindis+1;
        inc(gap[dis[now]]);
    end;
    exit(flow-ret);
end;

begin
    filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1); tot:=1;
    readln(n,m,d); source:=1; sink:=(1+n*m) << 1; number:=0;

    for i:=1 to n do
    begin readln(s);
        for j:=1 to m do
        begin
            inc(number); id[i,j,1]:=number << 1; id[i,j,2]:=id[i,j,1]+1;
            val(s[j],matrix); add(id[i,j,1],id[i,j,2],matrix);
        end;
    end;
    for i:=1 to n do
    begin readln(s);
        for j:=1 to m do if s[j]='L' then begin inc(lizard); add(source,id[i,j,1],1); end;
    end;
    for i:=1 to n do for j:=1 to m do if (i+d>n)or(i-d<1)or(j+d>m)or(j-d<1) then add(id[i,j,2],sink,maxlongint);
    for i:=1 to n do for j:=1 to m do for l:=1 to n do for r:=1 to m do if (i-l)*(i-l)+(j-r)*(j-r)<=d*d then add(id[i,j,2],id[l,r,1],maxlongint);

    n:=sink+1; gap[source]:=n;
    while dis[source]<n do inc(maxflow,Dfs(source,maxlongint));
    writeln(lizard-maxflow);
end.
posted @ 2019-01-25 22:02  _ARFA  阅读(141)  评论(0编辑  收藏  举报