zoukankan      html  css  js  c++  java
  • [NOI2020]美食家

    随便写写吧…

    显然方程式 (f_{t,u}) 表示 (t) 时间在 (u) 的最大贡献。

    (f_{t,u} = max{f_{t-w,v} + c_u})

    看到这范围绝对是矩阵快速幂了…

    等等边权不为(1)

    那就构造一个长度为 (5 imes n) 的向量嘛,然后每过一个时间就会移动。

    我们令 (id(i,j))(position)(i) 的时候,当前时间为 (6-j) 的状态。

    然后转移矩阵是考虑 (id(i,j+1) o id(i,j)) 的,然后连上边,注意有重边,如果没有注意的话会有奇奇怪怪的问题。

    如果有一条 ({u, v, w}) 的边,我们考虑

    base[0][id(u, 6 - w)][id(v, 5)] = c[v];
    

    实际意义是满足方程式。(

    然后就可以转移了。

    预处理 (log_2 10^9 = 30) 个矩阵,向量乘矩阵的复杂度是 ((5n)^2) 的。

    所以复杂度是 (((5n)^3 + (5n)^2k) imes log_2 t)

    #include <bits/stdc++.h>
    
    #define FOR(i, x, y) for (int i = x; i <= y; i++)
    #define ROF(i, x, y) for (int i = x; i >= y; i--)
    
    int n, m, T, k;
    int c[51];
    struct buf { int t, x, y; } q[201];
    
    struct Matrix {
    	long long a[251][251]; 
    	Matrix() { memset(a, 0xc0, sizeof(a)); }
    	long long* operator[](int x) { return a[x]; }
    } base[31];
    
    struct Vector {
    	long long a[251]; 
    	Vector() { memset(a, 0xc0, sizeof(a)); }
    	long long& operator[](int x) { return a[x]; }
    } answer;
    
    int lim;
    Matrix mul(Matrix a, Matrix b) {
    	Matrix c;
    	FOR(i, 1, lim)
    		FOR(j, 1, lim)
    			FOR(k, 1, lim)
    				c[i][j] = std::max(c[i][j], a[i][k] + b[k][j]);
    	return c;
    }
    
    Vector mul(Vector a, Matrix b) {
    	Vector c;
    	FOR(i, 1, lim)
    		FOR(j, 1, lim)
    			c[i] = std::max(c[i], a[j] + b[j][i]);
    	return c;
    }
    
    int id(int x, int y) { return x + (y - 1) * n; }
    int main() {
    #ifdef LOCAL
    	freopen("testdata.txt", "r", stdin);
    #endif
    	std::ios::sync_with_stdio(false);
    	std::cin.tie(NULL);
    	std::cin >> n >> m >> T >> k;
    	lim = n * 5;
    	FOR(i, 1, n) std::cin >> c[i];
    	FOR(i, 1, m) {
    		int u, v, w;
    		std::cin >> u >> v >> w;
    		base[0][id(u, 6 - w)][id(v, 5)] = c[v];
    	}
    	FOR(i, 1, k) {
    		int t, x, y;
    		std::cin >> t >> x >> y;
    		q[i] = {t, x, y};
    	}
    	std::sort(q + 1, q + k + 1, [](buf x, buf y) { return x.t < y.t; });
    	FOR(i, 1, n) FOR(j, 1, 4) base[0][id(i, j + 1)][id(i, j)] = 0;
    	FOR(i, 1, 30) base[i] = mul(base[i - 1], base[i - 1]);
    	answer[id(1, 5)] = c[1];
    	FOR(i, 1, k) {
    		int t = q[i].t - q[i - 1].t;
    		FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]);
    		answer[id(q[i].x, 5)] += q[i].y;
    	}
    	int t = T - q[k].t;
    	FOR(j, 0, 30) if (t >> j & 1) answer = mul(answer, base[j]);
    	std::cout << std::max(answer[id(1, 5)], -1ll) << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    Redis知识点
    MySQL InnoDB存储引擎知识点
    Java BIO、NIO 背后的理论知识
    分布式锁 & 分布式事务
    Kafka监控与JMX
    集合类源码(八)Collection之Set(HashSet, LinkedHashSet, TreeSet,ConcurrentSkipListSet)
    Kafka 基础知识
    JDK SPI 、Spring SPI、Dubbo SPI机制
    给老子爬爬爬!2019国家统计局最新城乡划分代码
    Linux系统使用教程
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/13565359.html
Copyright © 2011-2022 走看看