atcoder D Static Sushi

Problem Statement

"Teishi-zushi", a Japanese restaurant, is a plain restaurant with only one round counter. The outer circumference of the counter is C meters. Customers cannot go inside the counter.

Nakahashi entered Teishi-zushi, and he was guided to the counter. Now, there are N pieces of sushi (vinegared rice with seafood and so on) on the counter. The distance measured clockwise from the point where Nakahashi is standing to the point where the i-th sushi is placed, is xi meters. Also, the i-th sushi has a nutritive value of vi kilocalories.

Nakahashi can freely walk around the circumference of the counter. When he reach a point where a sushi is placed, he can eat that sushi and take in its nutrition (naturally, the sushi disappears). However, while walking, he consumes 1 kilocalories per meter.

Whenever he is satisfied, he can leave the restaurant from any place (he does not have to return to the initial place). On balance, at most how much nutrition can he take in before he leaves? That is, what is the maximum possible value of the total nutrition taken in minus the total energy consumed? Assume that there are no other customers, and no new sushi will be added to the counter. Also, since Nakahashi has plenty of nutrition in his body, assume that no matter how much he walks and consumes energy, he never dies from hunger.

题目链接

题目大意: 一个圈上有寿司,走的路程长度为消耗的能量,吃的的寿司为得到的能量,问最多获得能量是多少。

分析:

人走的方式有四种方式;

1、顺时针走,得到最大值

2、逆时针走,得到最大值

3、先顺时针,再返回起点,再逆时针

4、先逆时针,再返回起点,再顺时针

人为了得到最大能量,最多返回一次

首先计算出顺时针走到每个点的值a[i], 再计算出逆时针的每个点最终的能量值b[i]。 

若有返回,如顺时针则为a[i] - x[i] (回到起点消耗下x[i]) , 然后加上逆时针走到b[i + 1]的值。即a[i] - x[i] + b[i + 1];

然后四种情况进行一次比较

AC代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<string>
using namespace std;
#define LL long long 
const int MaxN = 1e5 + 7;
LL a[MaxN], b[MaxN];  
LL x[MaxN], v[MaxN];

int main()
{
	LL n, c;
	scanf("%lld %lld", &n, &c);
	for(int i = 1; i <= n; i++) 
		scanf("%lld %lld", &x[i], &v[i]);
	
	for(LL i = 1; i <= n; i++) 
		a[i] = a[i - 1] + v[i] - (x[i] - x[i - 1]);  // 顺时针走到i点时的能量
	x[n + 1] = c;
	for(LL i = n; i >= 1; i--) 
		b[i] = b[i + 1] + v[i] - (x[i+1] - x[i]);  // 逆时针走到i点时的能量

	for(LL i = 2; i <= n; i++) 
		a[i] = max(a[i-1], a[i]);  //走或者不走(和走之前的值进行比较)
	for(LL i = n-1; i >= 1; i--) 
		b[i] = max(b[i], b[i + 1]);

	LL ans = 0;
	for(LL i = 1; i <= n; i++) {
		ans = max(ans, a[i] - x[i] + b[i + 1]);  // 顺时针走后并返回一次的值
		ans = max(ans, b[i] - (c - x[i]) + a[i - 1]);  // 逆时针走后返回一次的值
		ans = max(ans, a[i]);  // 顺时针的最大值
		ans = max(ans, b[i]); //逆时针的最大值
	}

	printf("%lld\n", ans);
}

本来在计算走到i点的值的时候直接进行的比较求出的max(a[i-1], a[i - 1] + v[i] - (x[i] - x[i - 1]), 但是结果错误。因为a[i]的值需要准确的a[i-1],,而不是i点最大的值。

如样例 3 20 / 2 80 / 9 1 / 16 120   a[1] = 78, a[2] = 72, a[3] = 185.  

如果在之前就进行比较,那么a[2] = max(a[1], a[2]) = 78. 而a[3] 则就是从78的基础上进行改变的了即为191.

所以应该先算出到每个点的真正能量后再进行比较赋值。

猜你喜欢

转载自blog.csdn.net/weixin_40844130/article/details/80057725