Wave

题意:波浪数组满足四个条件:1、至少两个元素。2、奇数位的数都相等。3、偶数位的数都相等。4、奇数位和偶数位的数不相等。给你一个数组(数组中元素不大于c),你要从中找出波浪数组的最大长度。(保证波浪数组是该数组的一部分就行,就是可以在数组中任意按顺序挑选,使之满足波浪数组的条件)

这个题可以用动态规划(dp)来解。首先了解一下什么是dp。

  • 将一个复杂的问题分解成若干个子问题,通过综合子问题的最优解来得到原问题的最优解
  • 动态规划会将每个求解过的子问题的解记录下来,这样下一次碰到同样的子问题时,就可以直接使用之前记录的结果,而不是重复计算
  • 可以用递归或者递推的写法实现,递归的写法又叫记忆化搜索
  • 重叠子问题:如果一个问题可以被分解成若干个子问题,且这些子问题会重复出现,就称这个问题拥有重叠子问题。 一个问题必须拥有重叠子问题,才能用动态规划去解决。

首先我们来构造一个波浪数组,比如:1 2 1 2 1 2 1 2

很容易就发现当奇数位是1,偶数位是2的时候,波浪数组的排列一定是1后面是2,2后面是1,再1后面是2,2后面是1...

于是子问题就成了,当1出现的时候我们去找后面的2,并且ans++,当2出现的时候我们去找1,ans++...(因为分开来看,你找的只是波浪数组中的奇数位和偶数位的数字而已)

那么,如何来记录1 2 1 2 1 2 1 2这样的数组呢?

可以用一个二维数组巧妙地利用这两个相关的数组来记录他们出现的次数。

因为i的后面一定是j,j的后面一定是i.故dp[i][j]=dp[j][i]+1,dp[j][i]=dp[i][j]+1.这个计数方式妙处在于dp[i][j]中i是目前正在遍历的数字,而j是添加的后缀用来辨认下一个j来计数的。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector>

using namespace std;

typedef long long ll;
const int maxn=1e5+7;

int a[maxn];
int dp[105][105];

int main()
{
    freopen("input.txt","r",stdin);
    int n,c;
    cin>>n>>c;
    for(int i=0;i<n;i++) cin>>a[i];
    int maxlen=0;
    for(int i=0;i<n;i++)//所有元素 
    {
    	for(int j=1;j<c;j++)//从1到c遍历 
    	{
    		dp[a[i]][j]=dp[j][a[i]]+1;
    		if(a[i]==j) continue;
    		maxlen=max(maxlen,dp[a[i]][j]);
		}
	}
    cout<<maxlen<<endl;

    return 0;
}

可能的情况下,别相信暴力,也许暴力看起来粗暴简单,但正解也许更加巧妙提升思维。

原创文章 99 获赞 15 访问量 7338

猜你喜欢

转载自blog.csdn.net/qq_45328552/article/details/103092084