【思维题】CodeForce 1016C Vasya And The Mushrooms

版权声明:Johnson https://blog.csdn.net/m0_38055352/article/details/91481768

这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!

一、题目大意

题目的大致意思是,给定一个2×n的矩阵,从左上角开始走,每次走一个格子(上下左右),每次走一个格子的收获是:走过的步数×该格子中的值,要求每个格子必须都走到并且只能走一次,求如何走才能使收获最大。

二、题目思路以及AC代码

这题目我是做的比较晕的,最后也是看了题解才理解,以后还得加强这方面题的训练。

其实题目中给定每个格子必须都走到并且只能走一次,这已经把问题简化了。实际行走的重点只可能是如下情况。
在这里插入图片描述
因为要保证,每个格子走到且只走一次。

而且,实际行走路线就仅有以下两种形式。
在这里插入图片描述
在这里插入图片描述
可以看到,行走的形式就很固定了,终点列的左部就是一个蛇型的曲折路线,终点列的右部,要么顺时针,要么逆时针,然后采用前缀数组的形式存储。其实前缀数组这个部分我自己并没有想到,也是参照题解看明白的,大家没接触过的可能也需要仔细琢磨一下,我已经在代码中提供了注释。

下面给出AC代码:

#include <iostream>
#include <algorithm>
#define MAXN 300010
using namespace std;

typedef long long ll;

int n;

ll a[MAXN], b[MAXN];		// 原矩阵的两行
ll sum_per[MAXN];			// sum_per[i] 存储了第i列到第n列所有a[i],b[i]的和
ll sum_s[2*MAXN];			// sum_s[i] 当i在1~n的时候,存储的是a[1]~a[i]的和
							//			当i在n+1 ~ 2*n的时候,存储的是a[1]~a[n]的和再加上b[n]~b[2*n - i - 1]的和
ll sum_n[2*MAXN];			// sum_n[i] 当i在1~n的时候,存储的是b[1]~b[i]的和
							//			当i在n+1 ~ 2*n的时候,存储的是b[1]~b[n]的和再加上a[n]~a[2*n - i - 1]的和
ll sumr[MAXN];				// 终点列右部
ll suml[MAXN];				// 终点列左部

void table() {
	for (int i = n; i >= 1; i--) {
		sum_per[i] = sum_per[i + 1] + a[i] + b[i];
	}
	for (int i = 1; i <= n; i++) {
		sum_s[i] = sum_s[i - 1] + a[i] * (i - 1);
		sum_n[i] = sum_n[i - 1] + b[i] * (i - 1);
	}
	for (int i = n; i >= 1; i--) {
		sum_s[2 * n - i + 1] = sum_s[2 * n - i] + b[i] * (2 * n - i);
		sum_n[2 * n - i + 1] = sum_n[2 * n - i] + a[i] * (2 * n - i);
	}
	for (int i = 1; i <= n; i++) {
		if (i % 2) {
			sumr[i] = sum_s[2 * n - i + 1] - sum_s[i - 1] + (i - 1)*sum_per[i];
			suml[i] = suml[i - 1] + a[i - 1] * (2 * i - 3) + b[i - 1] * (2 * i - 4);
		}
		else {
			sumr[i] = sum_n[2 * n - i + 1] - sum_n[i - 1] + (i - 1)*sum_per[i];
			suml[i] = suml[i - 1] + a[i - 1] * (2 * i - 4) + b[i - 1] * (2 * i - 3);
		}
	}
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++) {
		cin >> b[i];
	}

	table();

	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = max(ans, sumr[i] + suml[i]);
	}

	cout << ans << endl;

    return 0;
}

如果有问题,欢迎大家指正!!!

猜你喜欢

转载自blog.csdn.net/m0_38055352/article/details/91481768