zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 3

    Problem A. Ascending Rating

    先学习一下单调队列与单调栈,其实和STL的也没啥区别,就是手动维护数组。

    POJ 2823

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e6 + 50;
    struct node
    {
        int x, val;
    };
    node q[maxn * 2];
    int minv[maxn], maxv[maxn];
    int a[maxn];
    int n, k;
    int main()
    {
        scanf("%d %d", &n, &k);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        int head = 1, tail = 0;
        int i = 1;
        q[++tail].val = a[i], q[tail].x = i;
        i++;
        for(; i < k; i++)
        {
            while(head <= tail && q[tail].val < a[i])
            {
                tail--;
            }
            q[++tail].val = a[i], q[tail].x = i;
        }
        if(k == 1) maxv[1] = q[head].val;
        for(; i <= n; i++)
        {
            while(head <= tail && q[tail].val < a[i])
            {
                tail--;
            }
            q[++tail].val = a[i], q[tail].x = i;
            if(q[head].x + k <= i) head++;
            maxv[i - k + 1] = q[head].val;
            //printf("%d
    ", maxv[i - k + 1]);
        }
        head = 1, tail = 0;
        q[++tail].val = a[1], q[tail].x = 1;
        i = 2;
        for(; i < k; i++)
        {
            while(head <= tail && q[tail].val > a[i])
            {
                tail--;
            }
            q[++tail].val = a[i], q[tail].x = i;
        }
        if(k == 1) minv[1] = q[head].val;
        for(; i <= n; i++)
        {
            while(head <= tail && q[tail].val > a[i])
            {
                tail--;
            }
            q[++tail].val = a[i], q[tail].x = i;
            if(q[head].x + k <= i) head++;
            minv[i - k + 1] = q[head].val;
        }
        int t = n - k + 1;
        for(int i = 1; i <= t; i++)
        {
            printf("%d", minv[i]);
            if(i < t) printf(" ");
            else printf("
    ");
        }
        for(int i = 1; i <= t; i++)
        {
            printf("%d", maxv[i]);
            if(i < t) printf(" ");
            else printf("
    ");
        }
        return 0;
    }
    /*
    8 1
    1 3 -1 -3 5 3 6 7
    */
    Code

    HDU 3530

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 50;
    int q1[maxn * 2], q2[maxn * 2], num[maxn];
    int main()
    {
        int n, m, k;
        while(scanf("%d %d %d", &n, &m, &k) != EOF)
        {
            for(int i = 1; i <= n; i++) scanf("%d", &num[i]);
            int he1 = 1, ta1 = 0, he2 = 1, ta2 = 0, ans = 0, cur = 1;
            for(int i = 1; i <= n; i++)
            {
                while(he1 <= ta1 && num[q1[ta1]] < num[i]) ta1--;
                while(he2 <= ta2 && num[q2[ta2]] > num[i]) ta2--;
                q1[++ta1] = i, q2[++ta2] = i;
                while(he1 <= ta1 && he2 <= ta2 && num[q1[he1]] - num[q2[he2]] > k)
                {
                    if(q1[he1] < q2[he2]) cur = q1[he1++] + 1;
                    else cur = q2[he2++] + 1;
                }
                if(he1 <= ta1 && he2 <= ta2 && num[q1[he1]] - num[q2[he2]] >= m)
                {
                    ans = max(ans, i - cur + 1);
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    Code

     本题和POJ2823很像,只不过是倒着扫,维护一个单调递减的区间。队列内的元素个数就是某个区间的最大值的变化数。

    为什么不能正着扫呢? 维护单调递增区间,不好处理那些在最大值后面的小值,把最大值去了,那些也没法加了。 可能有更麻烦的做法。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e7 + 50;
    typedef long long ll;
    int n, m, k, p, q, r;
    ll MOD;
    int a[maxn];
    int qq[maxn];
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            scanf("%d %d %d %d %d %d %lld", &n, &m, &k, &p, &q, &r, &MOD);
            for(int i = 1; i <= n; i++)
            {
                if(i <= k) scanf("%d", &a[i]);
                else a[i] = ((ll)p * a[i - 1] + (ll)q * i  + (ll)r) % MOD;
            }
            int head = 1, tail = 0;
            ll A = 0, B = 0;
            int i = n;
            for(; i > n - m + 1; i--)
            {
                while(head <= tail && a[qq[tail]] <= a[i]) tail--;
                qq[++tail] = i;
            }
            for(; i >= 1; i--)
            {
                while(head <= tail && a[qq[tail]] <= a[i]) tail--;
                qq[++tail] = i;
                if(head <= tail && qq[head] >= i + m) head++;
                A += (ll)a[qq[head]] ^ i;
                B += (ll)(tail - head + 1) ^ i;
               // printf("%d %d
    ", a[qq[head]], (tail - head + 1));
            }
            printf("%lld %lld
    ", A, B);
        }
        return 0;
    }
    
    
    
    
    
    /*
    1
    13 6 13 5 5 5 5
    13 12 11 10 9 8 7 6 5 4 3 2 1
    1
    10 1 10 5 5 5 5
    3 2 2 1 5 7 6 8 2 9
    */
    Code

    Problem C. Dynamic Graph Matching

    $f[i][s]$表示经过前i次操作后,s集合的点已经匹配的方案数。

    加边操作,递推公式:$f[i][s]=f[i-1][s]+f[i-1][s-u-v]。$

    $f[i-1][s]$表示不使用这条边的情况,$f[i-1][s-u-v]$表示使用这条边的情况,相加就得到添加一条边的情况。

    删边操作$f[i][s]=f[i-1][s]-f[i-1][s-u-v]$ 就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1111;
    int f[maxn];
    const ll mod = 1e9 + 7;
    int ans[11];
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            memset(f, 0, sizeof(f));
            int n, m;
            scanf("%d %d", &n, &m);
            char fu[5];
            int u, v;
            f[0] = 1;
            for(int i = 1; i <= m; i++)
            {
                scanf("%s %d %d",fu, &u, &v);
                u--, v--; ///从0开始表示点
                memset(ans, 0, sizeof(ans));
                for(int s = 0; s < (1 << n); s++)
                {
                    if(((1 << u) & s) && ((1 << v) & s))
                    {
                        int ccc = 0;
                        if(fu[0] == '+') f[s] = ((ll)f[s] + f[s - (1 << u) - (1 << v)]) % mod;
                        else f[s] = ((ll)f[s] - f[s - (1 << u) - (1 << v)] + mod) % mod;
                    }
                    if(f[s] != 0)
                    {
                        int st = s;
                        int cnt = 0;
                        while(st)
                        {
                            if(st & 1) cnt++;
                            st >>= 1;
                        }
                        ans[cnt / 2] = ((ll)ans[cnt / 2] + f[s]) % mod;
                    }
                }
                for(int ge = 1; ge <= (n >> 1); ge++)
                {
                    printf("%d", ans[ge]);
                    if(ge < (n >> 1)) printf(" ");
                    else printf("
    ");
                }
            }
        }
        return 0;
    }
    Code

    Problem G. Interstellar Travel

    先学习一发极角排序。

    POJ 2007

    逆时针走起,符合逆时针则 $>0。$

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int maxn = 100;
    struct Point
    {
        Point(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
        Point(){}
        int x, y;
    };
    Point point[maxn];
    Point operator - (Point A, Point B)
    {
        return Point(A.x - B.x, A.y - B.y);
    }
    int Cross(Point A, Point B)
    {
        return (A.x * B.y - A.y * B.x);
    }
    bool cmp(Point A, Point B)
    {
        int tmp = Cross(A - point[0], B - point[0]);
        if(tmp > 0) return 1;
        else if(tmp < 0) return false;
    }
    
    int main()
    {
        int cnt = 0;
        while(~scanf("%d %d", &point[cnt].x, &point[cnt].y))
        {
            cnt++;
        }
        sort(point + 1, point + cnt, cmp);
        for(int i = 0; i < cnt; i++)
        {
            printf("(%d,%d)
    ", point[i].x, point[i].y);
        }
        return 0;
    }
    Code

     整理个自己的凸包模板。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e3 + 50;
    const double PI = acos(-1.0);
    struct Point
    {
        Point(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
        Point(){}
        int x, y;
    
    };
    Point point[maxn];
    Point operator - (Point A, Point B)
    {
        return Point(A.x - B.x, A.y - B.y);
    }
    int Cross(Point A, Point B)
    {
        return (A.x * B.y - A.y * B.x);
    }
    Point pmin;
    double dis(Point A, Point B)
    {
        return sqrt((double)(A.x - B.x) * (A.x - B.x) + (double)(A.y - B.y) * (A.y - B.y));
    }
    bool cmp(Point A, Point B)
    {
        int tmp = Cross(A - point[1], B - point[1]);
        if(tmp > 0) return 1;
        else if(tmp == 0 && dis(A , pmin) < dis(B , pmin)) return 1;
        else  return false;
    }
    int top = 0;
    int st[maxn];
    void graham(int n)
    {
        if(n == 1)
        {
            top = 1, st[1] = 1;
        }
        else if(n == 2)
        {
            top = 2, st[1] = 1, st[2] = 2;
        }
        else
        {
            for(int i = 1; i <= 2; i++) st[i] = i;
            top = 2;
            for(int i = 3; i <= n; i++)
            {
                while(top >= 2 && Cross(point[st[top]] - point[st[top - 1]], point[i] - point[st[top - 1]]) <= 0)
                {
                    top--;
                }
                top++;
                st[top] = i;
            }
        }
    }
    double f(int x, int y)
    {
        return (double)x * x + (double)y * y;
    }
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            int n, L;
            scanf("%d %d", &n, &L);
            for(int i = 1; i <= n; i++) scanf("%d %d", &point[i].x, &point[i].y);
            ///要先找到最下,最左的点作为原点
            int k = 1;
            pmin.x = point[1].x, pmin.y = point[1].y;
            for(int i = 2; i <= n; i++)
            {
                if(pmin.y > point[i].y || (pmin.y == point[i].y && pmin.x > point[i].x))
                {
                    pmin.y = point[i].y;
                    pmin.x = point[i].x;
                    k = i;
                }
            }
            point[k] = point[1];
            point[1] = pmin;
            sort(point + 2, point + n + 1, cmp);
            top = 0;
            graham(n);
            double C = 0;
            for(int i = 1; i < top; i++)
            {
                C += (double)sqrt(f(point[st[i]].x - point[st[i+1]].x, point[st[i]].y - point[st[i+1]].y));
             //   printf("%lf
    ", C);
            }
            C += (double)sqrt(f(point[st[top]].x - point[st[1]].x, point[st[top]].y - point[st[1]].y));
            long long ans = 0;
            C += (double)2.0 * PI * L;
            printf("%.0lf
    ",C);
            if(T!=0) printf("
    ");
        }
        return 0;
    }
    Code

     去重点,去共线。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5 + 50;
    const double PI = acos(-1.0);
    struct Point
    {
        Point(ll _x, ll _y)
        {
            x = _x;
            y = _y;
        }
        Point(){}
        ll x, y;
        int id;
    
    };
    Point point[maxn];
    Point operator - (Point A, Point B)
    {
        return Point(A.x - B.x, A.y - B.y);
    }
    ll Cross(Point A, Point B)
    {
        return (A.x * B.y - A.y * B.x);
    }
    ll dis(Point A, Point B)
    {
        return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y);
    }
    bool cmp(Point A, Point B)
    {
        ll tmp = Cross(A - point[1], B - point[1]);
        if(tmp < 0LL) return 1;
        else if(tmp == 0 && dis(A , point[1]) < dis(B , point[1])) return 1;
        else if(tmp == 0 && dis(A , point[1]) == dis(B , point[1]))
        {
            return A.id < B.id;
        }
        else  return 0;
    }
    int top = 0;
    int st[maxn];
    void graham(int n)
    {
        if(n == 1)
        {
            top = 1, st[1] = 1;
        }
        else if(n == 2)
        {
            top = 2, st[1] = 1, st[2] = 2;
        }
        else
        {
            for(int i = 1; i <= 2; i++) st[i] = i;
            top = 2;
            for(int i = 3; i <= n; i++)
            {
                if(point[i].x == point[st[top]].x && point[i].y == point[st[top]].y) continue;
                while(top >= 2 && Cross(point[st[top]] - point[st[top - 1]], point[i] - point[st[top - 1]]) >= 0)
                {
                    if(Cross(point[st[top]] - point[st[top - 1]], point[i] - point[st[top - 1]]) > 0)
                    {
                        top--;
                    }
                    else
                    {
                        if(point[st[top]].id > point[i].id) ///共线,top的点属于线段中间的点,字典序较大,不符
                        {
                            top--;
                        }
                        else break;
                    }
                }
                top++;
                st[top] = i;
            }
        }
    }
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) scanf("%lld %lld", &point[i].x, &point[i].y), point[i].id = i;
            ///要先找到最下,最左的点作为原点
            sort(point + 2, point + n + 1, cmp);
            top = 1;
            graham(n);
            for(int i = 1; i <= top; i++)
            {
                printf("%d", point[st[i]].id);
                if(i < top) printf(" ");
                else printf("
    ");
            }
        }
        return 0;
    }
    /*
    123
    7
    0 0
    3 2
    1 1
    2 3
    3 2
    4 0
    1 3
    */
    Code

    Aguin的写法真的是天秀。。。。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5 + 10;
    ll x[maxn], y[maxn], id[maxn], st[maxn];
    bool cmp(int i, int j)
    {
        if(x[i] != x[j]) return x[i] < x[j];
        if(y[i] != y[j]) return y[i] > y[j];
        return i < j;
    }
    ll cross(int i, int j, int k)
    {
        return ((x[i] - x[k]) * (y[j] - y[k]) - (x[j] - x[k]) * (y[i] - y[k]));
    }
    vector<ll> can;
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            int n; scanf("%d", &n);
            for(int i = 1; i <= n; i++)
            {
                scanf("%lld %lld", &x[i], &y[i]);
                id[i] = i;
            }
            sort(id + 1, id + n + 1, cmp);
            can.clear();
            for(int i = 1; i <= n; i++) ///去掉重点,和x相等,较低的点
            {
                if(i == 1 || x[id[i]] > x[id[i - 1]]) can.push_back(id[i]);
            }
            int top = 0;
            for(int i = 0; i < can.size(); i++)
            {
                while(top >= 2 && cross(st[top], can[i], st[top - 1]) > 0) top--;
                while(top >= 2 && cross(st[top], can[i], st[top - 1]) == 0 && can[i] < st[top]) top--;
                st[++top] = can[i];
            }
            for(int i = 1; i <= top; i++) printf("%lld%c", st[i], i == top ? '
    ' : ' ');
        }
        return 0;
    }
    
    /*
    123
    7
    0 0
    3 2
    1 1
    2 3
    3 2
    4 0
    1 3
    */
    Code

    Problem I. Random Sequence

    不计复杂度的写法是:

    $dp[i][a[i]][a[i-1]][a[i-2]]+=dp[i-1][a[i-1]][a[i-2]][a[i-3]] imes v[gcd(a[i],a[i-1],a[i-2],a[i-3])]$

    复杂度应该是$O(m^4n)。$

    然后我们发现,在求$gcd(a[i],a[i-1],a[i-2],a[i-3])$的时候,如果$a[i]=2$,那么$a[i-1]=4$或者$6$都已经不重要,因为此时它的$gcd$最大是$2。$

    所以我们可以令

    $v1=a[i-1];$

    $v2=gcd(a[i-1],a[i-2]);$

    $v3=gcd(a[i-1],a[i-2],a[i-3]);$

    所以$v2$是$v1$的因子,即$v1|v2,v2|v3.$

    带入转移方程中:

    $dp[i][a[i]][gcd(a[i],v1)][gcd(a[i],v2)]+=dp[i-1][v1][v2][v3] imes v[gcd(a[i], v3)].$

    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        int cnt = 0;
        for(int i = 1; i <= 100; i++)
        {
            for(int j = 1; j <= 100; j++)
            {
                for(int k = 1; k <= 100; k++)
                {
                    if(i % j == 0 && j % k == 0)
                    {
                        cnt++;
                        printf("%d %d %d
    ", i, j, k);
                    }
                }
            }
        }
        printf("cnt = %d
    ", cnt);
    }
    ……
    100 100 5
    100 100 10
    100 100 20
    100 100 25
    100 100 50
    100 100 100
    cnt = 1471

    打表出来的状态只有$1471$个。

    复杂度$O(nmS).$

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 1e9 + 7;
    ll quick_pow(ll a, ll n)
    {
        ll res = 1;
        while(n)
        {
            if(n & 1) res = a * res % mod;
            n >>= 1;
            a = a * a % mod;
        }
        return res;
    }
    int gcd[101][101];
    int id[101][101][101], a[101];
    struct node
    {
        int v1, v2, v3;
    }st[1500];
    int cnt = 0;
    ll inv[101];
    void init()
    {
        for(int i = 1; i <= 100; i++) inv[i] = quick_pow(i, mod - 2);
        for(int i = 1; i <= 100; i++)
        {
            for(int j = 1; j <= 100; j++)
            {
                gcd[i][j] = __gcd(i, j);
            }
        }
        /// a[i-1]  gcd(a[i-1],a[i-2]) gcd(a[i-1],a[i-2],a[i-3])
        for(int i = 1; i <= 100; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                if(i % j != 0) continue;
                for(int k = 1; k <= j; k++)
                {
                    if(j % k != 0)continue;
                    st[++cnt] = node{i, j, k};
                    id[i][j][k] = cnt;
                }
            }
        }
    }
    ll v[101], dp[101][1500];
    int main()
    {
        init();
        ///printf("%d
    ", cnt);  1471
        int T; scanf("%d", &T);
        while(T--)
        {
            memset(dp, 0, sizeof(dp));
            int n, m; scanf("%d %d", &n, &m);
            for(int i = 1; i <= n; i++) scanf("%d", a + i);
            for(int i = 1; i <= m; i++) scanf("%lld", v + i);
            ///初始化前三个
            for(int i = 1; i <= m; i++)
            {
                if(a[3] && a[3] != i) continue;
                for(int j = 1; j <= m; j++)
                {
                    if(a[2] && a[2] != j) continue;
                    for(int k = 1; k <= m; k++)
                    {
                        if(a[1] && a[1] != k) continue;
                        int v1 = i;
                        int v2 = gcd[v1][j];
                        int v3 = gcd[v2][k];
                        int net = id[v1][v2][v3];
                        dp[3][net]++;
                       // printf("%d %d %d
    ", v1, v2, v3);
                    }
                }
            }
            for(int i = 3; i < n; i++) ///枚举的是a[i+1]
            {
                for(int j = 1; j <= cnt; j++)
                {
                    if(dp[i][j])
                    {
                        int v1 = st[j].v1, v2 = st[j].v2, v3 = st[j].v3;
                        for(int k = 1; k <= m; k++)
                        {
                            if(a[i + 1] && a[i + 1] != k) continue;
                            int net = id[k][gcd[k][v1]][gcd[k][v2]];
                           // printf("%d %d
    ", i + 1, net);
                            dp[i + 1][net] = (dp[i + 1][net] + dp[i][j] * v[gcd[k][v3]] % mod) % mod;
                           // printf("%d %lld %lld
    ", gcd[k][v3], v[gcd[k][v3]], dp[i+1][net]);
                        }
                    }
                }
            }
            ll ans = 0;
            for(int i = 1; i <= cnt; i++)
            {
                ans = (ans + dp[n][i]) % mod;
            }
            for(int i = 1; i <= n; i++)
            {
                if(!a[i]) ans = (ans * inv[m]) % mod;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    /*
    23
    4 3
    0 0 0 0
    3 2 4
    */
    Code

    Problem M. Walking Plan

    首先最容易想到的状态是$G[i][j][k]$,表示从$i$到$j$最少经过$k$条路径。

    状态转移方程是:$G[i][j][k]=min(G[i][j][k],G[i][p][k-1]+g[p][j])$,表示从$p$到$j$有一条路径。

    时间复杂度是$O(n^3 k).$  肯定超时。

    然后就真香系列……

    https://blog.csdn.net/qq_34454069/article/details/81292814

    注意此处DPa应该是DPb。

    还有个坑点是$DPc[i][j][k]$枚举至少经过$k$条路径的时候,应该从$k=0$开始。因为询问可以是$100$的整数倍。

    #include <bits/stdc++.h>
    using namespace std;
    int w[55][55];
    int dist[55][55]; ///跑一遍Floyd求两点最短路
    const int INF = 0x3f3f3f3f;
    ///k <= 100
    int dp0[51][51][101]; ///经过刚好k*100条边
    int dp1[51][51][101]; ///刚好经过k条边
    int dp2[51][51][101]; ///至少经过k条边的最短路
    int main()
    {
       // printf("%d
    ", INF + INF);
        int T; scanf("%d", &T);
        while(T--)
        {
            int n, m; scanf("%d %d", &n, &m);
            memset(w, INF, sizeof(w));
            memset(dist, INF, sizeof(dist));
            memset(dp0, INF, sizeof(dp0));
            memset(dp1, INF, sizeof(dp1));
            memset(dp2, INF, sizeof(dp2));
            for(int i = 1; i <= m; i++)
            {
                int u, v, val; scanf("%d %d %d", &u, &v, &val);
                w[u][v] = min(w[u][v], val);
                dist[u][v] = w[u][v];
            }
            for(int i = 1; i <= n; i++)
            {
                dist[i][i] = 0;
                dp1[i][i][0] = 0;
                dp0[i][i][0] = 0;
                dp2[i][i][0] = 0;
            }
            ///Floyd
            for(int k = 1; k <= n; k++)
            {
                for(int i = 1; i <= n; i++)
                {
                    for(int j = 1; j <= n; j++)
                    {
                        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                    }
                }
            }
            ///刚好经过k条边
            for(int k = 1; k <= 100; k++)
            {
                for(int l = 1; l <= n; l++)
                {
                    for(int i = 1; i <= n; i++)
                    {
                        for(int j = 1; j <= n; j++)
                        {
                            dp1[i][j][k] = min(dp1[i][j][k], dp1[i][l][k - 1] + w[l][j]);
                        }
                    }
                }
            }
           // printf("%d
    ", dist[2][2]);
            ///刚好经过k*100条边
            for(int k = 1; k <= 100; k++)
            {
                for(int l = 1; l <= n; l++)
                {
                    for(int i = 1; i <= n; i++)
                    {
                        for(int j = 1; j <= n; j++)
                        {
                            dp0[i][j][k] = min(dp0[i][j][k], dp0[i][l][k - 1] + dp1[l][j][100]);
                        }
                    }
                }
            }
            ///至少经过k条边
            for(int k = 0; k <= 100; k++)
            {
                for(int l = 1; l <= n; l++)
                {
                    for(int i = 1; i <= n; i++)
                    {
                        for(int j = 1; j <= n; j++)
                        {
                            dp2[i][j][k] = min(dp2[i][j][k], dp1[i][l][k] + dist[l][j]);
                        }
                    }
                }
            }
            int q; scanf("%d", &q);
            while(q--)
            {
                int s, t, k;
                scanf("%d %d %d", &s, &t, &k);
                int ans = INF;
                for(int i = 1; i <= n; i++)
                {
                    ans = min(ans, dp0[s][i][k / 100] + dp2[i][t][k % 100]);
                }
                printf("%d
    ", ans == INF ? -1 : ans);
            }
        }
        return 0;
    }
    Code
  • 相关阅读:
    Java 异步编程
    对@repository,@Service, @Compent,@Controller注解的理解
    分布式锁的解决方案
    JVM垃圾收集器
    java死锁
    CountDownLatch和CylicBarrier以及Semaphare你使用过吗
    必懂知识——HashMap的实现原理
    重写equals为啥需要重写hashCode
    mysql数据库的索引
    mysql常见的优化策略
  • 原文地址:https://www.cnblogs.com/littlepear/p/9394064.html
Copyright © 2011-2022 走看看