把图中每个点拆成两个点,流量为1,费用为原图点的权值。相邻的点连一条边,费用为0,流量为1.
view code#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF = 1<<30;
const int N = 1010;
const int M = N*15;
int _, cas=1, n, m, s, t;
char str[5][N];
bool inq[M];
int d[M];
int p[M];
int a[M];
int pre[M];
struct edge
{
int u, v, cap,cost, next;
edge() {}
edge(int u, int v, int cap,int cost, int next):u(u),v(v),cap(cap),cost(cost),next(next) {}
}e[200*N];
int ecnt = 0;
int getid(int x, int y)
{
return x*n+y+1;
}
void addedge(int u,int v, int cap, int cost)
{
e[ecnt] = edge(u, v, cap, cost, pre[u]);
pre[u] = ecnt++;
e[ecnt] = edge(v, u, 0, -cost, pre[v]);
pre[v] = ecnt++;
}
bool BellmanFort(int &flow, int &cost)
{
for(int i=s; i<=t; i++) d[i] = INF;
memset(inq, 0, sizeof(inq));
d[s] = 0; p[s] = 0; a[s] = INF;
queue<int >q;
q.push(s);
while(!q.empty())
{
int u = q.front(); q.pop();
inq[u] = 0;
for(int i=pre[u]; ~i; i=e[i].next)
{
int v = e[i].v;
if(e[i].cap>0 && d[v]>d[u]+e[i].cost)
{
d[v] = d[u] + e[i].cost;
p[v] = i;
a[v] = min(a[u], e[i].cap);
if(!inq[v])
{
q.push(v);
inq[v] = 1;
}
}
}
}
if(d[t]==INF) return false;
flow += a[t];
cost += d[t]*a[t];
int u = t;
while(u!=s)
{
e[p[u]].cap -= a[t];
e[p[u]^1].cap += a[t];
u = e[p[u]].u;
}
return true;
}
int Mincost()
{
int flow = 0, cost = 0;
while(BellmanFort(flow, cost)) ;
return cost;
}
void solve()
{
for(int i=0; i<5; i++) scanf("%s", str[i]);
ecnt = 0;
int B = getid(4,n-1)+1;
s = 0, t = getid(5,0)+B;
memset(pre, -1, sizeof(pre));
for(int i=0; i<5; i++)
{
if(str[i][0]==‘@‘) addedge(s, getid(i, 0), 1, 0);
for(int j=0; j<n; j++)
{
if(str[i][j]==‘@‘) addedge(getid(i, j), getid(i,j)+B, 1, 0);
else addedge(getid(i, j), getid(i,j)+B, 1, str[i][j]-‘0‘);
if(i>0) addedge(getid(i, j)+B, getid(i-1, j), 1, 0);
if(i<4) addedge(getid(i, j)+B, getid(i+1, j), 1, 0);
if(j<n-1) addedge(getid(i, j)+B, getid(i, j+1), 1, 0);
if(j>0) addedge(getid(i, j)+B, getid(i, j-1), 1, 0);
}
addedge(getid(i,n-1)+B, t, INF, 0);
}
cout<<Mincost()<<endl;
}
int main()
{
// freopen("in.txt", "r", stdin);
while(scanf("%d", &n)>0 && n) solve();
return 0;
}