• bzoj2668


    对于这种题很容易看出是费用流吧……

    但这道题不容易建模;

    首先是怎么表示目标状态和其实状态,看起来有黑有白很复杂

    但实际上,不难发现,白色格子没什么用,起决定作用的是黑格子

    也就是我们可以把问题简化:我们怎么把开始的黑格子移到目标位置

    但这个移动不是一般的移动;

    在一条路径中,不难发现,起始两点是只要交换一次,其他路径上个点都是要交换2次

    由于题目给出的限制是点的交换次数限制c,所以不难想到要拆点

    但是平常的拆两点好像无法表示这个特征,

    于是我们就拆成3个点……

        p1--->p0--->p2

    p1表示交换进来,p2表示交换出去;

    所以不难得出:

    对于每个点,如果它是原图中的黑点,连边<p1,p0,c/2,0>,<p0,p2,(c+1)/2,0>,<s,p0,1,0>;

    如果它是新图中的黑点,连边<p1,p0,(c+1)/2>,<p0,p2,c/2,0>,<p0,t,1,0>;

    注意存在有的点在新图原图都是黑点的情况(在这里WA了一次)

    如果它在两个图中都是白点,那么连边<p1,p0,c/2,0>,<p0,p2,c/2,0>

    最后对于原图中任意可达两点,连边<pi2,pj1,inf,1>

    注意这道题可以交换对角线,还要判断是否可行,细节挺多

      1 const dx:array[1..8] of integer=(-1,1,0,0,1,-1,-1,1);
      2       dy:array[1..8] of integer=(0,0,1,-1,1,-1,1,-1);
      3       inf=10000007;
      4 type node=record
      5        next,point,cost,flow:longint;
      6      end;
      7 
      8 var edge:array[0..1000010] of node;
      9     p,pre,cur,d:array[0..2010] of longint;
     10     v:array[0..2010] of boolean;
     11     a,b,c:array[0..30,0..30] of integer;
     12     q:array[0..1001000] of longint;
     13     ch,t,n,m,i,j,k,x,y,po,tot,sum,ans,len:longint;
     14     s:string;
     15 
     16 procedure add(x,y,f,w:longint);
     17   begin
     18     inc(len);
     19     edge[len].point:=y;
     20     edge[len].flow:=f;
     21     edge[len].cost:=w;
     22     edge[len].next:=p[x];
     23     p[x]:=len;
     24   end;
     25 
     26 function spfa:boolean;
     27   var i,x,y,f,r:longint;
     28   begin
     29     fillchar(v,sizeof(v),false);
     30     v[0]:=true;
     31     for i:=1 to t do
     32       d[i]:=inf;
     33     d[0]:=0;
     34     f:=1;
     35     r:=1;
     36     q[f]:=0;
     37     while f<=r do
     38     begin
     39       x:=q[f];
     40       v[x]:=false;
     41       i:=p[x];
     42       while i<>-1 do
     43       begin
     44         y:=edge[i].point;
     45         if edge[i].flow>0 then
     46           if d[y]>d[x]+edge[i].cost then
     47           begin
     48             d[y]:=d[x]+edge[i].cost;
     49             pre[y]:=x;
     50             cur[y]:=i;
     51             if not v[y] then
     52             begin
     53               inc(r);
     54               q[r]:=y;
     55               v[y]:=true;
     56             end;
     57           end;
     58         i:=edge[i].next;
     59       end;
     60       inc(f);
     61     end;
     62     if d[t]=inf then exit(false) else exit(true);
     63   end;
     64 
     65 procedure mincost;
     66   var i,j,neck:longint;
     67   begin
     68     while spfa do
     69     begin
     70       i:=t;
     71       neck:=inf;
     72       while i<>0 do
     73       begin
     74         j:=cur[i];
     75         if neck>edge[j].flow then neck:=edge[j].flow;
     76         i:=pre[i];
     77       end;
     78       i:=t;
     79       while i<>0 do
     80       begin
     81         j:=cur[i];
     82         dec(edge[j].flow,neck);
     83         inc(edge[j xor 1].flow,neck);
     84         i:=pre[i];
     85       end;
     86       ans:=ans+d[t]*neck;
     87       dec(ch,neck);
     88       if ch=0 then break;
     89     end;
     90   end;
     91 
     92 begin
     93   readln(n,m);
     94   len:=-1;
     95   fillchar(p,sizeof(p),255);
     96   t:=3*n*m+1;
     97   for i:=1 to n do
     98   begin
     99     readln(s);
    100     for j:=1 to m do
    101     begin
    102       a[i,j]:=ord(s[j])-48;
    103       tot:=tot+a[i,j];
    104     end;
    105   end;
    106   for i:=1 to n do
    107   begin
    108     readln(s);
    109     for j:=1 to m do
    110     begin
    111       b[i,j]:=ord(s[j])-48;
    112       sum:=sum+b[i,j];
    113     end;
    114   end;
    115   for i:=1 to n do
    116   begin
    117     readln(s);
    118     for j:=1 to m do
    119       c[i,j]:=ord(s[j])-48;
    120   end;
    121   if sum<>tot then
    122   begin
    123     writeln(-1);
    124     halt;
    125   end
    126   else ch:=sum;
    127   sum:=n*m;
    128   for i:=1 to n do
    129   begin
    130     for j:=1 to m do
    131     begin
    132       x:=(i-1)*m+j;
    133       if a[i,j]=1 then
    134       begin
    135         add(x+sum,x,c[i,j] shr 1,0);
    136         add(x,x+sum,0,0);
    137         add(x,x+2*sum,(c[i,j]+1) shr 1,0);
    138         add(x+2*sum,x,0,0);
    139         add(0,x,1,0);
    140         add(x,0,0,0);
    141         if b[i,j]=1 then    //细节
    142         begin
    143           add(x,t,1,0);
    144           add(t,x,0,0);
    145         end;
    146       end
    147       else if b[i,j]=1 then
    148       begin
    149         add(x+sum,x,(c[i,j]+1) shr 1,0);
    150         add(x,x+sum,0,0);
    151         add(x,x+2*sum,c[i,j] shr 1,0);
    152         add(x+2*sum,x,0,0);
    153         add(x,t,1,0);
    154         add(t,x,0,0);
    155       end
    156       else if (a[i,j]+b[i,j]=0) then
    157       begin
    158         add(x+sum,x,c[i,j] shr 1,0);
    159         add(x,x+sum,0,0);
    160         add(x,x+2*sum,c[i,j] shr 1,0);
    161         add(x+2*sum,x,0,0);
    162       end;
    163     end;
    164   end;
    165 
    166   for i:=1 to n do
    167     for j:=1 to m do
    168     begin
    169       po:=(i-1)*m+j;
    170       for k:=1 to 8 do
    171       begin
    172         x:=i+dx[k];
    173         y:=j+dy[k];
    174         if (x<=n) and (y<=m) and (x>0) and (y>0) then
    175         begin
    176           tot:=(x-1)*m+y;
    177           add(po+2*sum,tot+sum,inf,1);
    178           add(tot+sum,po+2*sum,0,-1);
    179         end;
    180       end;
    181     end;
    182   mincost;
    183   if ch<>0 then writeln(-1) else writeln(ans);
    184 end.
    View Code
  • 相关阅读:
    反序列化二叉树-队列
    二叉树中和为某一值的路径
    深拷贝复杂链表
    机器人运动范围
    vue 安装及使用
    json 函数
    js 获取当前时间
    JS编码方式
    搭建自己的Webpack项目
    webpack 安装 打包
  • 原文地址:https://www.cnblogs.com/phile/p/4473249.html
Copyright © 2020-2023  润新知