#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=b;i>=a;--i)
using namespace std;
inline ll read()
{
ll x=0,f=1;
char c=getchar();
while (c<'0' || c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0' && c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
inline void print(ll x)
{
if(x < 0) putchar('-'), x = -x;
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
return ;
}
const int N = 1e3;
const int M = (N << 2);
ll a[N], b[N], g[N][N];
ll d[N], q[N], hd, tl;
ll mf[N], vis[N], nxt[M << 1], to[M << 1], head[N], cnt = 1, c[M << 1], pre[N], cur[N], w[M << 1];
void add(int x, int y, ll cc, ll z)
{
nxt[++cnt] = head[x];
to[cnt] = y;
c[cnt] = cc;
w[cnt] = z;
head[x] = cnt;
}
const ll inf = 1145141919810;
bool spfa(int st, int ed)
{
//spfa不用初始化vis数组
memset(d, 0x3f, sizeof(d));
memset(mf, 0, sizeof(mf));
hd = tl = 0;
vis[st] = 1;
d[st] = 0;
mf[st] = inf;
q[++tl] = st;
while(hd < tl)
{
int x = q[++hd];
vis[x] = 0;
for(int i = head[x]; i; i = nxt[i])
{
int y = to[i];
if(d[y] > d[x] + w[i] && c[i])
{
d[y] = d[x] + w[i];
mf[y] = min(mf[x], c[i]);
pre[y] = i;
if(!vis[y]) q[++tl] = y, vis[y] = 1;
}
}
}
return mf[ed] > 0;
}
int tot = 0;
void EK(int st, int ed)
{
tot++;
ll flow = 0, now = ed, cost = 0;
while(spfa(st, ed))
{
now = ed;
while(now != st)
{
int i = pre[now];
c[i] -= mf[ed];
c[i ^ 1] += mf[ed];
now = to[i ^ 1];
}
flow += mf[ed];
cost += mf[ed] * d[ed];//整条路都是 mf[ed] 所以只需要路径长度 * 流量即可
}
cout << -cost << endl;
}
void ad(int x, int y, ll c, ll w)
{
add(x, y, c, w);
add(y, x, 0, -w);
}
int id[N][N];
int main(){
int m = read(), n = read();
rep(i, 0, n - 1)
rep(j, 1, m + i)
g[i + 1][j] = -read(), id[i + 1][j] = ++tot;
int st = 2 * tot + 1;
int ed = st + 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= i + m - 1; ++j)
ad(id[i][j], id[i][j] + tot, 1, 0);
for(int j = 1; j <= m; ++j)
ad(st, id[1][j], 1, g[1][j]);//第一行
for(int i = 1; i <= n - 1; ++i)
for(int j = 1; j <= i + m - 1; ++j)
ad(id[i][j] + tot, id[i + 1][j], 1, g[i + 1][j]),
ad(id[i][j] + tot, id[i + 1][j + 1], 1, g[i + 1][j + 1]);
for(int j = 1; j <= n + m - 1; ++j)
ad(id[n][j] + tot, ed, 1, 0);
EK(st, ed);
//2
memset(head, 0, sizeof(head)); cnt = 1;
for(int j = 1; j <= m; ++j)
ad(st, id[1][j], 1, g[1][j]);//第一行
for(int i = 1; i <= n - 1; ++i)
for(int j = 1; j <= i + m - 1; ++j)
ad(id[i][j], id[i + 1][j], 1, g[i + 1][j]),
ad(id[i][j], id[i + 1][j + 1], 1, g[i + 1][j + 1]);
for(int j = 1; j <= n + m - 1; ++j)
ad(id[n][j], ed, inf, 0);
EK(st, ed);
//3
memset(head, 0, sizeof(head)); cnt = 1;
for(int j = 1; j <= m; ++j)
ad(st, id[1][j], 1, g[1][j]);//第一行
for(int i = 1; i <= n - 1; ++i)
for(int j = 1; j <= i + m - 1; ++j)
ad(id[i][j], id[i + 1][j], inf, g[i + 1][j]),
ad(id[i][j], id[i + 1][j + 1], inf, g[i + 1][j + 1]);
for(int j = 1; j <= n + m - 1; ++j)
ad(id[n][j], ed, inf, 0);
EK(st, ed);
return 0;
}
首先我想知道 为什么N1e3还能RE 然后我想知道 为什么N改成4e3之后前两个点会T 欢迎dalao指点