BJOI 2017 Kakuro

Description
 
Input
Output
 
Sample Input
样例输入1
8 8
0 1 1 0 0 1 1 1
2 4 4 0 3 4 4 4
2 4 4 3 4 4 4 4
2 4 4 4 4 4 1 0
0 2 4 4 3 4 4 1
0 1 3 4 4 4 4 4
2 4 4 4 4 2 4 4
2 4 4 4 0 2 4 4
23 30 27 12 16
16 9 7 17 24 8 7 9
17 8 9 15 29 8 9 5 7
35 6 8 5 9 7 12
7 6 1 7 8 2 6 7
11 10 16 4 6 1 3 2
21 8 9 3 1 5 1 4
6 3 1 2 3 2 1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1
样例输入2
5 5
0 1 1 1 1
2 4 4 4 4
2 4 4 3 4
2 4 4 4 4
2 4 4 4 4
16 8 6 8
4 4 9 5 4
12 8 4 19 10 4
14 2 3 3 6
1 7 9 4 5
17 5 10 13
11 15 16 4 14
20 20 15 5 16 3
4 3 19 2 4
19 19 13 15 20
Sample Output
样例输出1
0
样例输出2
822
 Data Constraint
 
Code:
#include<bits/stdc++.h>
using namespace std;
#define MAX 37
#define N (47*47<<2|7)
#define M (N<<3|7)
#define LL long long
#define eho(x) for(int i=head[x];i;i=net[i])
#define v fall[i]
#define inf 143323223
#define Min(a,b) (a<b?a:b)
//#define int LL
struct Lxf{
    int S,T,tot,head[N],fall[M],net[M],lim[M],cost[M],la[N],lat[N],dis[N];
    LL cs;
    Lxf() {tot=1;}
    void Add(int x,int y,int Lim,int Cost){
        fall[++tot]=y; net[tot]=head[x]; head[x]=tot; lim[tot]=Lim; cost[tot]=Cost;
    }
    void add(int x,int y,int Lim,int Cost){
        Add(x,y,Lim,Cost); Add(y,x,0,-Cost);
    }
    bool spfa() {
        static queue<int> Q;
        static int in[N],x;
        memset(dis,121,sizeof dis);
        dis[S]=0;
        dis[S]=0; in[S]=1; Q.push(S);
        while (!Q.empty()) {
            x=Q.front(); Q.pop();
            eho(x) 
             if (lim[i]&&dis[x]+cost[i]<dis[v]) {
              dis[v]=dis[x]+cost[i],la[v]=i,lat[v]=x;
              if (!in[v])  in[v]=1,Q.push(v);
            }
            in[x]=0;
        }
        return dis[T]<0;
    }
    LL Flow(int s,int t,int &flow) {
        S=s; T=t;
        flow=0; cs=0;
        while (spfa()) {
            int fl=inf;
            for (int i=t;i!=s;i=lat[i])  fl=Min(fl,lim[la[i]]);
            cs+=1ll*fl*dis[T]; flow+=fl;
            for (int i=t;i!=s;i=lat[i])  lim[la[i]]-=fl,lim[la[i]^1]+=fl;
        }
        return cs;
    }
    bool check() {
        for(int i=1;i<=tot;i+=2) {
            if(cost[i]==inf&&lim[i^1]>0)  return 0;
            if(cost[i]==-inf&&lim[i]>0)   return 0;
        }
        return 1;
    }
}G;
int n,m,Tp[MAX][MAX],IdC[MAX][MAX],Line[MAX][MAX],IdL[MAX][MAX],Ori[MAX][MAX],Column[MAX][MAX],cnt,Left[MAX][MAX],dow;
void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
LL ans,CO;
template <class T>
inline void read(T& x){
    static char c; static int b;
    for (c=getchar(),b=1;!isdigit(c);c=getchar()) if (c=='-') b=-1;
    for (x=0;isdigit(c);c=getchar()) x=x*10+c-48;
    x*=b;
}
int ChangeC[MAX][MAX],ChangeL[MAX][MAX],ChangeO[MAX][MAX],Up[MAX][MAX],AfterC[MAX][MAX],AfterL[MAX][MAX],AfterO[MAX][MAX];
signed main () {
    freopen("kakuro.in","r",stdin);
    freopen("kakuro.out","w",stdout);
    read(n); read(m);
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++) read(Tp[i][j]);
    for (int i=1;i<=n;i++) 
     for (int j=1;j<=m;j++) {
         if(Tp[i][j]==1||Tp[i][j]==3) {
            read(Column[i][j]);
            IdC[i][j]=++cnt;
        }
        if(Tp[i][j]==2||Tp[i][j]==3) {
            read(Line[i][j]);
            IdL[i][j]=++cnt;
        }
        if(Tp[i][j]==4) read(Ori[i][j]);
     }
     for (int i=1;i<=n;i++) 
        for (int j=1;j<=m;j++) {
            if(Tp[i][j]==1||Tp[i][j]==3) {
                read(ChangeC[i][j]);
                if(ChangeC[i][j]==-1)  ChangeC[i][j]=inf;
            }
            if(Tp[i][j]==2||Tp[i][j]==3) {
                read(ChangeL[i][j]);
                if(ChangeL[i][j]==-1)  ChangeL[i][j]=inf;
            }
            if(Tp[i][j]==4) {
                read(ChangeO[i][j]);
                if(ChangeO[i][j]==-1) ChangeO[i][j]=inf;
            }
        }
    for(int i=1;i<=n;i++) 
        for (int j=1;j<=m;j++) {
            if(Tp[i][j]==1||Tp[i][j]==3) {
                int k=i+1;
                while(k<=n&&Tp[k][j]==4) Up[k++][j]=IdC[i][j];
                AfterC[i][j]=k-i-1;
                ans+=1ll*ChangeC[i][j]*abs(AfterC[i][j]-Column[i][j]);
            }
            if(Tp[i][j]==2||Tp[i][j]==3) {
                int k=j+1;
                while(k<=M&&Tp[i][k]==4) Left[i][k++]=IdL[i][j];
                AfterL[i][j]=k-j-1;
                ans+=1ll*ChangeL[i][j]*abs(AfterL[i][j]-Line[i][j]);
            }
            if(Tp[i][j]==4) {
                AfterO[i][j]=1;
                ans+=1ll*ChangeO[i][j]*abs(AfterO[i][j]-Ori[i][j]);
            }
        }
    for (int i=1;i<=n;i++) 
        for (int j=1;j<=m;j++) {
            if(Tp[i][j]==1||Tp[i][j]==3) {
                if(AfterC[i][j] < Column[i][j]) 
                    G.add(0,IdC[i][j],Column[i][j]-AfterC[i][j],-ChangeC[i][j]);
                G.add(0,IdC[i][j],inf,ChangeC[i][j]);
            }
            if(Tp[i][j]==2||Tp[i][j]==3) {
                if(AfterL[i][j] < Line[i][j]) 
                    G.add(IdL[i][j],cnt+1,Line[i][j]-AfterL[i][j],-ChangeL[i][j]);
                G.add(IdL[i][j],cnt+1,inf,ChangeL[i][j]);
            }
            if(Tp[i][j]==4) {
                if(AfterO[i][j]<Ori[i][j]) 
                    G.add(Up[i][j],Left[i][j],Ori[i][j]-AfterO[i][j],-ChangeO[i][j]);
                G.add(Up[i][j],Left[i][j],inf,ChangeO[i][j]);
            }
        }
    CO=G.Flow(0,cnt+1,dow);
    return writeln(G.check()?ans+CO:-1),0;
}

 

转载于:https://www.cnblogs.com/rrsb/p/9878733.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值