Codeforces 351C Jeff and Brackets matrix optimization DP

The meaning of problems: on paper you want a length of n * m bracketed sequence, the i-th position takes Videos left parenthesis is a [i% n], right parenthesis is spent Videos b [i% n], Q the minimum cost parentheses unfinished sequence. n <= 20, m <= 1e7

Ideas: If n and m restrictions regardless of the question to do well, provided DP [i] [j] is to position i, j is the balance factor cost, dp [i] [j] = min (dp [i - 1] [j - 1] + a [i], dp [i - 1] [j + 1] + b [i]), but this level of n * m to 2e8, which we can not afford. However, we can find a nature: the size of the balance factor of no more than 2 * n, because if more than 2 * n, we can not change an answer by exchanging the order, so the balance factor is less than 2 * n. We think about the transfer dp, we have found may be one matrix multiplication is performed once transferred (disposed transition matrix is ​​C), then C [j] [j + 1] = a [i], C [j] [j - 1 ] = b [i], then by once this matrix to perform a transfer, because a and b are arrays of length n cycle, then we can again handle the n-th matrix transfer (seen from the associative matrix multiplication) and then fast matrix power to perform such a shift n times m times, we get a final answer.

Code:

#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]);
}

  

Guess you like

Origin www.cnblogs.com/pkgunboat/p/10990308.html