C1. Pokémon Army (easy version) Codeforces Round #672 (Div. 2)

原题链接

一个有意思的dp

题目

在这里插入图片描述
在这里插入图片描述

输入

3
3 0
1 3 2
2 0
1 2
7 0
1 2 5 4 3 6 7

输出

3
2
9

Note

In third test case we can build an army in such way: [1 2 5 4 3 6 7], its strength will be 5−3+7=9.

题意

从原数组a中找k个数,组成b数组,要保证 1≤b1<b2<⋯<bk≤n,
然后进行b1−b2+b3−b4+… .操作,求操作后的最大值是多少。

思路

减完之后要加,加完之后又要减,所以用dp保留上一步操作的结果,与下次操作后做对比,取最大值。

dp公式:

dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);

dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);

推导

dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);

//在一次减操作后可以选择加一个数,也可以选择不加任何数
//dp[i - 1][0]表示在上一次减操作后不加任何数,维持原状态
//dp[i - 1][1] + a[i]表示在上一步减操作后加一个数

dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);

//同理,在一次加操作后可以选择不减任何数,也可以选择减去一个数

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <cmath>
#include <map>
#include <list>
#include <set>
#include <cstdlib>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 10;
const int N = 10010;
const int INF = 0x3f3f3f3f;
const ll  LNF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const double eps = 10e-6;
const double PI = 3.14159265358979323;
typedef pair<int, int> PII;
priority_queue<int, vector<int>, less<int> >q;
priority_queue<int, vector<int>, greater<int> >qq;

ll a[maxn];//存放数组值
ll dp[maxn][2];//用于存放当前状态,dp[][0]表示进行加操作,dp[][1]表示进行减操作
int main () {
	int t;
	scanf ("%d", &t);
	while (t--) {
		int n, q;
		scanf ("%d %d", &n, &q);
		for (int i = 1; i <= n; i++) {
			scanf ("%lld", &a[i]);
		}
		for (int i = 1; i <= n; i++){
			//因为多组输入,所以dp清空数组
			dp[i][0] = 0;
			dp[i][1] = 0;
		}
		for (int i = 1; i <= n; i++){
			dp[i][0] = max (dp[i - 1][0], dp[i - 1][1] + a[i]);
			//在一次减操作后可以选择加一个数,也可以选择不加任何数
			//dp[i - 1][0]表示在上一次减操作后不加任何数,维持原状态
			//dp[i - 1][1] + a[i]表示在上一步减操作后加一个数
			dp[i][1] = max (dp[i - 1][1], dp[i - 1][0] - a[i]);
			//同理,在一次加操作后可以选择不减任何数,也可以选择减去一个数
		}
		ll ans = max (dp[n][0], dp[n][1]);
		printf ("%lld\n", ans);
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值