zoukankan      html  css  js  c++  java
  • 省队集训 Day3 陈姚班

    【题目大意】

    给一张网格图,上往下有流量限制,下往上没有,左往右有流量限制。

    $n * m leq 2.5 * 10^6$

    【题解】

    考场直接上最大流,50分。竟然傻逼没看出狼抓兔子。

    平面图转对偶图,其中没有流量限制(inf)不用转,然后直接在DAG上分层dp即可。

    复杂度$O(nm)$,但是这样过不去被卡常了。

    出题人的做法是先处理出每层初始的那个随机数,然后每层往下直接做,这样因为是一维数组,所以寻址方便,不会被卡常。

    我的做法是动态开数组(用new),然后比较两维大小来分配第一维给谁,第一维优先分配给小的,第二维给大的。

    然后如果n >= m可以用指针优化,所以阈值设为n * 10 >= m即可(虽然没啥必要)

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 2.5e5 + 10;
    const int mod = 1e9+7;
    
    namespace irand {
        int A, B, Q, X0;
        inline void getseed() {
            cin >> A >> B >> Q >> X0;
        }
        inline int getint() {
            return X0 = (1ll * A * X0 + B) % Q;
        }
    }
    
    int n, m, **ad, **bd;
    ll f[M];
    
    int main() {
        cin >> n >> m; irand :: getseed();
        if(n * 10 >= m) {
            ad = new int*[m + 5]; bd = new int*[m + 5]; --n;
            for (register int i=1; i<=m; ++i) ad[i] = new int[n + 5], bd[i] = new int[n + 5];
            for (register int i=1; i<=n; ++i)
                for (register int j=1; j<=m; ++j)
                    ad[j][i] = irand :: getint();
            
            for (register int i=1; i<n; ++i)
                for (register int j=1; j<m; ++j)
                    bd[j][i] = irand :: getint();
                    
            for (register int i=1; i<m; ++i) {
                register int *A = ad[i], *B = bd[i];
                for (register int j=1; j<=n; ++j) f[j] += A[j];
                for (register int j=2; j<=n; ++j) f[j] = min(f[j], f[j-1]+B[j-1]);
                for (register int j=n-1; j; --j) f[j] = min(f[j], f[j+1]+B[j]);
            }
            ll ans = 1e18;
            for (int i=1; i<=n; ++i) f[i] += ad[m][i];
            for (int i=1; i<=n; ++i) ans = min(ans, f[i]);
            cout << ans << endl;
            return 0;
        } else {
            ad = new int*[n + 5]; bd = new int*[n + 5]; --n;
            for (register int i=1; i<=n; ++i) ad[i] = new int[m + 5], bd[i] = new int[m + 5];
            for (register int i=1; i<=n; ++i)
                for (register int j=1; j<=m; ++j)
                    ad[i][j] = irand :: getint();
            
            for (register int i=1; i<n; ++i)
                for (register int j=1; j<m; ++j)
                    bd[i][j] = irand :: getint();
                    
            for (register int i=1; i<m; ++i) {
                for (register int j=1; j<=n; ++j) f[j] += ad[j][i];
                for (register int j=2; j<=n; ++j) f[j] = min(f[j], f[j-1]+bd[j-1][i]);
                for (register int j=n-1; j; --j) f[j] = min(f[j], f[j+1]+bd[j][i]);
            }
            ll ans = 1e18;
            for (int i=1; i<=n; ++i) f[i] += ad[i][m];
            for (int i=1; i<=n; ++i) ans = min(ans, f[i]);
            cout << ans << endl;
            return 0;
        }
    }
    View Code
  • 相关阅读:
    【2017.12.02普及组模拟】送快递
    【NOIP2013模拟联考7】OSU
    顺序表元素位置倒置示例c++实现
    c++字符串排序
    JAVA实现四则运算的简单计算器
    JAVA图形小动画之简单行星运动
    JAVA多线程编程
    ege图形库之简单贪吃蛇(c++)
    ege图形库之动画排序
    c语言中一种典型的排列组合算法
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170709_c.html
Copyright © 2011-2022 走看看