zoukankan      html  css  js  c++  java
  • 洛谷 P4013 数字梯形问题

    ->题目链接

    题解:

    网络流。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #define N 4010
    #define inf 1000000000
    using namespace std;
    int a[N][N],head[N],dis[N],inq[N],fa[N],n,m,num,cnt,S,T;
    struct node {
        int u,v,pre,f,w;
    } e[N];
    void add(int u,int v,int f,int w) {
        e[++cnt].u=u;e[cnt].v=v;
        e[cnt].f=f;e[cnt].w=w;
        e[cnt].pre=head[u];head[u]=cnt;
        e[++cnt].u=v;e[cnt].v=u;
        e[cnt].f=0;e[cnt].w=-w;
        e[cnt].pre=head[v];head[v]=cnt;
    }
    bool spfa() {
        for(int i=0; i<=T; i++) dis[i]=inf;
        queue<int> q;
        q.push(S);
        inq[S]=1;
        dis[S]=0;
        while(!q.empty()) {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for(int i=head[u]; i; i=e[i].pre)
                if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w) {
                    dis[e[i].v]=dis[u]+e[i].w;
                    fa[e[i].v]=i;
                    if(!inq[e[i].v]) {
                        inq[e[i].v]=1;
                        q.push(e[i].v);
                    }
                }
        }
        return dis[T]!=inf;
    }
    void mincost() {
        int cost=0;
        while(spfa()) {
            int tmp=fa[T],x=inf;
            while(tmp) {
                int u=e[tmp].u;
                x=min(x,e[tmp].f);
                tmp=fa[e[tmp].u];
            }
            tmp=fa[T];
            while(tmp) {
                e[tmp].f-=x;
                e[tmp^1].f+=x;
                tmp=fa[e[tmp].u];
            }
            cost+=x*dis[T];
        }
        printf("%d
    ",-cost);
    }
    int hao(int i,int j) {
        return (m*2+i-2)*(i-1)/2+j;
    }
    void build1() {
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1; i<=m; i++)
            add(S,i,1,-a[1][i]);
        for(int i=1; i<n; i++)
            for(int j=1; j<=m+i-1; j++)
                add(hao(i,j)+num,hao(i+1,j),1,-a[i+1][j]),add(hao(i,j)+num,hao(i+1,j+1),1,-a[i+1][j+1]);
        for(int i=1; i<=m+n-1; i++)
            add(hao(n,i)+num,T,1,0);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m+i-1; j++)
                add(hao(i,j),hao(i,j)+num,1,0);
    
    }
    void build2() {
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1; i<=m; i++)
            add(S,i,1,-a[1][i]);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m+i-1; j++)
                add(hao(i,j),hao(i+1,j),1,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),1,-a[i+1][j+1]);
        for(int i=1; i<=m+n-1; i++)
            add(hao(n,i),T,inf,0);
    }
    void build3() {
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1; i<=m; i++)
            add(S,i,1,-a[1][i]);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m+i-1; j++)
                add(hao(i,j),hao(i+1,j),inf,-a[i+1][j]),add(hao(i,j),hao(i+1,j+1),inf,-a[i+1][j+1]);
        for(int i=1; i<=m+n-1; i++)
            add(hao(n,i),T,inf,0);
    }
    int main() {
        scanf("%d%d",&m,&n);
        num=(m*2+n-1)*n/2;
        S=0;
        T=num*2+1;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m+i-1; j++)
                scanf("%d",&a[i][j]);
        build1();
        mincost();
        build2();
        mincost();
        build3();
        mincost();
        return 0;
    }  
    AC

    我走我的独木桥。

  • 相关阅读:
    换零钞
    空心菱形
    生成回文数
    机器人数目
    胡同门牌号
    七星填数
    阶乘位数
    打印数字
    平方末尾
    数位和
  • 原文地址:https://www.cnblogs.com/GTBD/p/9435890.html
Copyright © 2011-2022 走看看