Codeforces 351C Jeff and Brackets 矩阵优化DP

题意:你要在纸上画一个长度为n * m的括号序列,第i个位置画左括号的花费是a[i % n], 画右括号的花费是b[i % n],问画完这个括号序列的最小花费。n <= 20, m <= 1e7

思路:如果不管n和m的限制,这个题很好做,设dp[i][j]是到i位置,平衡因子是j的花费,dp[i][j] = min(dp[i - 1][j - 1] + a[i], dp[i - 1][j + 1] + b[i]),但是这样n * m到2e8级别,这是我们无法承受的。不过,我们可以发现一个性质:平衡因子的大小不会超过2 * n,因为如果超过2 * n,我们可以通过交换顺序而不改变答案,让平衡因子都小于2 * n。我们想一下dp的转移,我们发现可以用一次矩阵乘法来执行一次转移(设转移矩阵是C),那么C[j][j + 1] = a[i],C[j][j - 1] = b[i],那么乘一次这个矩阵就执行了一次转移,因为a和b数组是长度为n的循环,那么我们可以一次处理出n次转移的矩阵(由矩阵乘法的结合律可知),再用矩阵快速幂执行这样的n次转移m次,就得到了最终的答案。

代码:

#include <bits/stdc++.h>
#define INF 2e9
#define LL long long
using namespace std;
int a[30], b[30], N;
struct Matrix {
	LL a[55][55];
	Matrix(int x = INF) {
		memset(a, 0x3f, sizeof(a));
		for (int i = 0; i < N; i++)
			a[i][i] = x;
	}
	friend Matrix operator * (const Matrix& A, const Matrix& B) {
		Matrix ans;
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++)
				for (int k = 0; k < N; k++)
					ans[i][j] = min(ans[i][j], A[i][k] + B[k][j]);
		return ans;
	}
	Matrix operator ^ (int y) {
		Matrix x = *this, ans(0);
		for (; y; y >>= 1) {
			if(y & 1) ans = ans * x;
			x = x * x;
		}
		return ans;
	}
	LL*operator [](int x) {
		return a[x];
	}
	const LL*operator [](int x) const {
		return a[x];
	}
};

int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++)
		scanf("%d", &b[i]);
	N = 2 * n + 1;
	Matrix dp, A(0);
	dp[0][0] = 0;
	for (int i = 1; i <= n; i++) {
		Matrix tmp;
		for (int j = 0; j <= N; j++) {
			if(j) tmp[j - 1][j] = a[i];
			if(j < 2 * n) tmp[j + 1][j] = b[i];
		}
		A = A * tmp;
	}
	dp = dp * (A ^ m);
	printf("%lld\n", dp[0][0]);
}

  

原文地址:https://www.cnblogs.com/pkgunboat/p/10990308.html

时间: 2024-11-07 07:17:27

Codeforces 351C Jeff and Brackets 矩阵优化DP的相关文章

bzoj 3120 矩阵优化DP

我的第一道需要程序建矩阵的矩阵优化DP. 题目可以将不同的p分开处理. 对于p==0 || p==1 直接是0或1 对于p>1,就要DP了.这里以p==3为例: 设dp[i][s1][s2][r]为前i列,结尾为0的有s1行(0表示女生,1表示男生),结尾为01的有s2个,结尾为011的有n-s1-s2个,有r列全是1的方案数. 状态这么复杂,看起来一点也不能用矩阵优化,但我们可以将状态(s1,s2,r)hash成整数,然后建立状态之间的转移. 收获: 这种m超过10^7的一般都要用矩阵优化,如

Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks(矩阵优化DP)

题目链接:点击打开链接 题意:给n个数作为一个块,有b个块,从其中若干个中选择数,每个块只能选一个数,最后组成一个数模x等于k的方法数. 思路:很容易想到这样一个DP方程 : 用dp[i][j]表示现在i位,余数是j.那么dp[i + 1][(j * 10 + k) % x] = dp[i][j] * cnt[k],k是指枚举放1~9中哪一位. 因为b特别大,显然要矩阵优化,知道了DP方程,其实矩阵的构造特别简单. 根据矩阵相乘的规则, 其实这个矩阵就是A[j][(j*10+a[k])%x]++

BZOJ1297 [SCOI2009]迷路 【矩阵优化dp】

题目 windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间. 输入格式 第一行包含两个整数,N T. 接下来有 N 行,每行一个长度为 N 的字符串. 第i行第j列为'0'表示从节点i到节点j没有边. 为'1'到'9'表示从节点i到节点j需要耗费的时间. 输出格式 包含一个整数,可能的路径数

bzoj1009 GT考试 (kmp+矩阵优化dp)

设f[i][j]是到第i位 已经匹配上了j位的状态数 然后通过枚举下一位放0~9,可以用kmp处理出一个转移的矩阵 然后就可以矩阵快速幂了 1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxm=22; 7 8 inline

「模拟8.21」山洞(矩阵优化DP)

暴力: 正解: 考虑循环矩阵,f[i][j]表示从i点到j点的方案数 我们发现n很小,我们预处理出n次的f[i][j] 然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fir[i][j] 但是此时的循环为三层 我们考虑转移式子的意义在0-n次从i-j,在n+1到2×n转移至j 这样此时的j-k其实可以把他看作从0开始走j-k步本质上是一样的 然后还有一个特判,就不讲了 for(int j=0;j<n;++j) { ff[now][j]=(ff[now][j]+ff[las

poj3734 Blocks[矩阵优化dp or 组合数学]

Blocks Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6578   Accepted: 3171 Description Panda has received an assignment of painting a line of blocks. Since Panda is such an intelligent boy, he starts to think of a math problem of paint

形态形成场(矩阵乘法优化dp)

形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 \(A=12312301231230,B=1231230,C=123\).现在对于给定的替换式,求字符 AA 所代表的串有多少子串满足: 这个子串为单个字符\(0\)或没有前导\(0\). 把这个子串看作一个十进制数后模\(n\)等于\(0\). 答案对\(r\)取模.对于100%的数据,$2 \l

poj3744--Scout YYF I(概率dp第五弹:矩阵优化)

Scout YYF I Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5093   Accepted: 1385 Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy's base. After overcoming a series difficulties,

HDU 5607 graph(矩阵优化+概率DP)

该题很容易想到求概率的转移方程:用d[i][j]表示第i步,走到j点的概率. 但是该题的k高达1e9,所以按照套路,要用矩阵相乘来优化. 第一次写矩阵相乘, 大概的意思就是利用矩阵实现递推, 并且因为每次递推的过程一样, 所以就相当于右乘这个矩阵的k次方. 用矩阵快速幂即可. 矩阵相乘这个问题, 大概可以看成, 矩阵中的每个元素表示到该点的概率, 那么另一个矩阵就是DP矩阵, 表示当前一步到各点的概率, 矩阵相乘就等于下一步到各点的概率(矩阵乘法的意义). 另外, 要对答案进行1e9+5次方再取