カカのマトリックス旅行

POJ

ロス・グー

所与の(N * N \)\行列、各セルは、非負整数有する(\ A_ {I、J}、(A_ {I、J} <= 1000))\を今から、(1(\ 1)\)出発、あなたが右折またはダウンして、最終的にすることができます\((N-、N-)\) それぞれの数は、グリッドから取り出し、グリッドに達し、グリッド数がとなり(0 \ \)総歩行ように(K \)\回、今必要\(K \)と正方形を達成する最大回数を。\((1 <= N - <= 50、0 <= K <= 10 )。\)

分析:建設コストフローモデル(変換点側、スプリット点法)各グリッド\は、((I、J \) ノードに対応する\((1-I)* N-J + \)点に分割します、そして、アウト点、点有向エッジ、1の容量は、ポイントのコストは、二つの格子接続する\((i、j)は\ ) 最初の点で表現数(削除数であります);別の容量\(1-K \) コスト(\ 0 \)の後に(それは示される点を通る、もはや)にアクセスすることはできません。)\ \((I、J)をもポイントでありますする\((I、J + 1 )\) と\((I + 1、J )\) の容量を有する点でも有向エッジ\(k個の\) コスト(\ 0 \)が取得する方法( )アクセスすることができません。

次に\((1,1)\)のソース点で、\((N、N-)\)は、シンクノードであり、最大流量は、最もコストを行うことができます。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=200005;//懒得想数组具体要开多大了
int n,k,s,t,max_flow,ans;
int dis[N],visit[N],pre[N],incf[N];
int tot,head[N],nxt[N],to[N],limit[N],w[N];
inline void add(int a,int b,int c,int d){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;limit[tot]=c;w[tot]=d;
    nxt[++tot]=head[b];head[b]=tot;
    to[tot]=a;limit[tot]=0;w[tot]=-d;
}
inline bool spfa(){
    for(int i=1;i<N;++i)dis[i]=-1e9,visit[i]=0;
    queue<int>q;q.push(s);dis[s]=0;visit[s]=1;
    incf[s]=1<<30;
    while(q.size()){
        int u=q.front();q.pop();visit[u]=0;
        for(int i=head[u];i;i=nxt[i]){
            if(!limit[i])continue;
            int v=to[i];
            if(dis[v]<dis[u]+w[i]){
                dis[v]=dis[u]+w[i];
                incf[v]=min(incf[u],limit[i]);
                pre[v]=i;
                if(!visit[v])visit[v]=1,q.push(v);
            }
        }
    }
    if(dis[t]==-1e9)return false;
    return true;
}
inline void update(){
    int x=t;
    while(x!=s){
        int i=pre[x];
        limit[i]-=incf[t];
        limit[i^1]+=incf[t];
        x=to[i^1];
    }
    max_flow+=incf[t];
    ans+=dis[t]*incf[t];
}
int main(){
    n=read(),k=read();s=1;t=2*n*n;tot=1;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            int val=read();
            add((i-1)*n+j,(i-1)*n+j+n*n,1,val);
            add((i-1)*n+j,(i-1)*n+j+n*n,k-1,0);
            if(j+1<=n)add((i-1)*n+j+n*n,(i-1)*n+j+1,k,0);
            if(i+1<=n)add((i-1)*n+j+n*n,i*n+j,k,0);
        }
    }
    while(spfa())update();
    printf("%d\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/PPXppx/p/11614185.html