zoukankan      html  css  js  c++  java
  • BZOJ2668: [cqoi2012]交换棋子

    题解:

    可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html

    其实自己yy一下就知道这样建图的正确性了。

    感觉太神奇,居然还能拆成3个点

    orzzzzzzzzzzzzzzzzzzzzzzzzz

    跪跪跪跪跪跪跪跪

    代码:

      1 #include<cstdio>
      2   
      3 #include<cstdlib>
      4   
      5 #include<cmath>
      6   
      7 #include<cstring>
      8   
      9 #include<algorithm>
     10   
     11 #include<iostream>
     12   
     13 #include<vector>
     14   
     15 #include<map>
     16   
     17 #include<set>
     18   
     19 #include<queue>
     20   
     21 #include<string>
     22   
     23 #define inf 1000000000
     24   
     25 #define maxn 200000+5
     26   
     27 #define maxm 200000+5
     28   
     29 #define eps 1e-10
     30   
     31 #define ll long long
     32   
     33 #define pa pair<int,int>
     34   
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36   
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38   
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40   
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42   
     43 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
     44   
     45 #define mod 1000000007
     46   
     47 using namespace std;
     48   
     49 inline int read()
     50   
     51 {
     52   
     53     int x=0,f=1;char ch=getchar();
     54   
     55     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     56   
     57     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     58   
     59     return x*f;
     60   
     61 }
     62 int n,m,k,mincost,tot,s,t,head[maxn],d[maxn],from[2*maxm];
     63 bool v[maxn];
     64 queue<int>q;
     65 int a[100][100][3],num[100][100][3],cnt[3];
     66 struct edge{int from,go,next,v,c;}e[2*maxm];
     67 void add(int x,int y,int v,int c)
     68 {
     69     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
     70     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
     71 }
     72 bool spfa()
     73 {
     74     for (int i=s;i<=t;i++){v[i]=0;d[i]=inf;}
     75     q.push(s);d[s]=0;v[s]=1;
     76     while(!q.empty())
     77     {
     78         int x=q.front();q.pop();v[x]=0;
     79         for (int i=head[x],y;i;i=e[i].next)
     80          if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])
     81          {
     82             d[y]=d[x]+e[i].c;from[y]=i;
     83             if(!v[y]){v[y]=1;q.push(y);}
     84          }
     85     }
     86     return d[t]!=inf;
     87 }
     88 void mcf()
     89 {
     90     mincost=0;
     91     while(spfa())
     92     {
     93         int tmp=inf;
     94         for(int i=from[t];i;i=from[e[i].from]) tmp=min(tmp,e[i].v);
     95         mincost+=d[t]*tmp;
     96         for(int i=from[t];i;i=from[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;}
     97     }
     98 }
     99 const int dx[8]={0,0,1,-1,1,1,-1,-1};
    100 const int dy[8]={1,-1,0,0,-1,1,1,-1};
    101   
    102 int main()
    103   
    104 {
    105     n=read();m=read();s=0;t=3*n*m+1;
    106     for0(k,2)for1(i,n)for1(j,m)
    107     {
    108         char ch=getchar();
    109         while(ch<'0'||ch>'9')ch=getchar();
    110         a[i][j][k]=ch-'0';
    111         //cout<<i<<' '<<j<<' '<<k<<' '<<a[i][j][k]<<endl;
    112         num[i][j][k]=++tot;
    113         cnt[k]+=a[i][j][k];
    114     }
    115     //cout<<tot<<' '<<s<<' '<<t<<endl;
    116     tot=1;
    117     for1(i,n)for1(j,m)
    118     {
    119         if(a[i][j][0]&&a[i][j][1])a[i][j][0]=a[i][j][1]=0;
    120         if(a[i][j][0])
    121         {
    122             add(num[i][j][1],num[i][j][0],a[i][j][2]/2,0);
    123             add(num[i][j][0],num[i][j][2],(a[i][j][2]+1)/2,0);
    124             add(s,num[i][j][0],1,0);
    125         }
    126         else if(a[i][j][1])
    127         {
    128             add(num[i][j][1],num[i][j][0],(a[i][j][2]+1)/2,0);
    129             add(num[i][j][0],num[i][j][2],a[i][j][2]/2,0);
    130             add(num[i][j][0],t,1,0);
    131         }
    132         else
    133         {
    134             add(num[i][j][1],num[i][j][0],a[i][j][2]/2,0);
    135             add(num[i][j][0],num[i][j][2],a[i][j][2]/2,0);
    136         }
    137         for0(k,7)
    138         {
    139             int x=i+dx[k],y=j+dy[k];
    140             if(x<1||x>n||y<1||y>m)continue;
    141             add(num[i][j][2],num[x][y][1],inf,1);
    142         }
    143     }
    144     if(cnt[0]!=cnt[1]){printf("-1
    ");return 0;}
    145     mcf();
    146     printf("%d
    ",mincost);
    147   
    148     return 0;
    149   
    150 }  
    View Code

    2668: [cqoi2012]交换棋子

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 673  Solved: 235
    [Submit][Status]

    Description

    有一个nm列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。

    Input

    第一行包含两个整数nm(1<=n, m<=20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0~9数字的字符串,表示每个格子参与交换的次数上限。
     

    Output

    输出仅一行,为最小交换总次数。如果无解,输出-1。

    Sample Input

    3 3
    110
    000
    001
    000
    110
    100
    222
    222
    222

    Sample Output

    4
  • 相关阅读:
    ZOJ Problem Set–2417 Lowest Bit
    ZOJ Problem Set–1402 Magnificent Meatballs
    ZOJ Problem Set–1292 Integer Inquiry
    ZOJ Problem Set–1109 Language of FatMouse
    ZOJ Problem Set–1295 Reverse Text
    ZOJ Problem Set–1712 Skew Binary
    ZOJ Problem Set–1151 Word Reversal
    ZOJ Problem Set–1494 Climbing Worm
    ZOJ Problem Set–1251 Box of Bricks
    ZOJ Problem Set–1205 Martian Addition
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4182161.html
Copyright © 2011-2022 走看看